2014-12-11 03:00:42 +08:00
|
|
|
//===--- UnwrappedLineFormatter.cpp - Format C++ code ---------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2014-12-11 03:00:42 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-04-19 21:02:15 +08:00
|
|
|
#include "NamespaceEndCommentsFixer.h"
|
2014-12-11 03:00:42 +08:00
|
|
|
#include "UnwrappedLineFormatter.h"
|
|
|
|
#include "WhitespaceManager.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
2016-07-19 03:02:11 +08:00
|
|
|
#include <queue>
|
2014-12-11 03:00:42 +08:00
|
|
|
|
|
|
|
#define DEBUG_TYPE "format-formatter"
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace format {
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
bool startsExternCBlock(const AnnotatedLine &Line) {
|
|
|
|
const FormatToken *Next = Line.First->getNextNonComment();
|
|
|
|
const FormatToken *NextNext = Next ? Next->getNextNonComment() : nullptr;
|
2015-06-17 17:43:56 +08:00
|
|
|
return Line.startsWith(tok::kw_extern) && Next && Next->isStringLiteral() &&
|
2014-12-11 03:00:42 +08:00
|
|
|
NextNext && NextNext->is(tok::l_brace);
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Tracks the indent level of \c AnnotatedLines across levels.
|
2015-05-12 17:23:57 +08:00
|
|
|
///
|
|
|
|
/// \c nextLine must be called for each \c AnnotatedLine, after which \c
|
|
|
|
/// getIndent() will return the indent for the last line \c nextLine was called
|
|
|
|
/// with.
|
|
|
|
/// If the line is not formatted (and thus the indent does not change), calling
|
|
|
|
/// \c adjustToUnmodifiedLine after the call to \c nextLine will cause
|
|
|
|
/// subsequent lines on the same level to be indented at the same level as the
|
|
|
|
/// given line.
|
|
|
|
class LevelIndentTracker {
|
|
|
|
public:
|
|
|
|
LevelIndentTracker(const FormatStyle &Style,
|
|
|
|
const AdditionalKeywords &Keywords, unsigned StartLevel,
|
|
|
|
int AdditionalIndent)
|
2015-05-12 18:16:02 +08:00
|
|
|
: Style(Style), Keywords(Keywords), AdditionalIndent(AdditionalIndent) {
|
2015-05-12 17:23:57 +08:00
|
|
|
for (unsigned i = 0; i != StartLevel; ++i)
|
|
|
|
IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Returns the indent for the current line.
|
2015-05-12 17:23:57 +08:00
|
|
|
unsigned getIndent() const { return Indent; }
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Update the indent state given that \p Line is going to be formatted
|
2015-05-12 17:23:57 +08:00
|
|
|
/// next.
|
|
|
|
void nextLine(const AnnotatedLine &Line) {
|
|
|
|
Offset = getIndentOffset(*Line.First);
|
2015-06-11 18:14:13 +08:00
|
|
|
// Update the indent level cache size so that we can rely on it
|
|
|
|
// having the right size in adjustToUnmodifiedline.
|
|
|
|
while (IndentForLevel.size() <= Line.Level)
|
|
|
|
IndentForLevel.push_back(-1);
|
2015-05-12 17:23:57 +08:00
|
|
|
if (Line.InPPDirective) {
|
2015-05-12 18:16:02 +08:00
|
|
|
Indent = Line.Level * Style.IndentWidth + AdditionalIndent;
|
2015-05-12 17:23:57 +08:00
|
|
|
} else {
|
|
|
|
IndentForLevel.resize(Line.Level + 1);
|
|
|
|
Indent = getIndent(IndentForLevel, Line.Level);
|
|
|
|
}
|
|
|
|
if (static_cast<int>(Indent) + Offset >= 0)
|
|
|
|
Indent += Offset;
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Update the indent state given that \p Line indent should be
|
2017-06-14 20:29:47 +08:00
|
|
|
/// skipped.
|
|
|
|
void skipLine(const AnnotatedLine &Line) {
|
|
|
|
while (IndentForLevel.size() <= Line.Level)
|
|
|
|
IndentForLevel.push_back(Indent);
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Update the level indent to adapt to the given \p Line.
|
2015-05-12 17:23:57 +08:00
|
|
|
///
|
|
|
|
/// When a line is not formatted, we move the subsequent lines on the same
|
|
|
|
/// level to the same indent.
|
|
|
|
/// Note that \c nextLine must have been called before this method.
|
|
|
|
void adjustToUnmodifiedLine(const AnnotatedLine &Line) {
|
|
|
|
unsigned LevelIndent = Line.First->OriginalColumn;
|
|
|
|
if (static_cast<int>(LevelIndent) - Offset >= 0)
|
|
|
|
LevelIndent -= Offset;
|
2015-06-17 17:43:56 +08:00
|
|
|
if ((!Line.First->is(tok::comment) || IndentForLevel[Line.Level] == -1) &&
|
2015-05-12 17:23:57 +08:00
|
|
|
!Line.InPPDirective)
|
|
|
|
IndentForLevel[Line.Level] = LevelIndent;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Get the offset of the line relatively to the level.
|
2015-05-12 17:23:57 +08:00
|
|
|
///
|
|
|
|
/// For example, 'public:' labels in classes are offset by 1 or 2
|
|
|
|
/// characters to the left from their level.
|
|
|
|
int getIndentOffset(const FormatToken &RootToken) {
|
|
|
|
if (Style.Language == FormatStyle::LK_Java ||
|
|
|
|
Style.Language == FormatStyle::LK_JavaScript)
|
|
|
|
return 0;
|
|
|
|
if (RootToken.isAccessSpecifier(false) ||
|
|
|
|
RootToken.isObjCAccessSpecifier() ||
|
2015-12-01 20:05:04 +08:00
|
|
|
(RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
|
|
|
|
RootToken.Next && RootToken.Next->is(tok::colon)))
|
2015-05-12 17:23:57 +08:00
|
|
|
return Style.AccessModifierOffset;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Get the indent of \p Level from \p IndentForLevel.
|
2015-05-12 17:23:57 +08:00
|
|
|
///
|
|
|
|
/// \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(ArrayRef<int> IndentForLevel, unsigned Level) {
|
|
|
|
if (IndentForLevel[Level] != -1)
|
|
|
|
return IndentForLevel[Level];
|
|
|
|
if (Level == 0)
|
|
|
|
return 0;
|
|
|
|
return getIndent(IndentForLevel, Level - 1) + Style.IndentWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FormatStyle &Style;
|
|
|
|
const AdditionalKeywords &Keywords;
|
2015-05-12 19:14:06 +08:00
|
|
|
const unsigned AdditionalIndent;
|
2015-05-12 18:16:02 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// The indent in characters for each level.
|
2015-05-12 17:23:57 +08:00
|
|
|
std::vector<int> IndentForLevel;
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Offset of the current line relative to the indent level.
|
2015-05-12 17:23:57 +08:00
|
|
|
///
|
|
|
|
/// For example, the 'public' keywords is often indented with a negative
|
|
|
|
/// offset.
|
|
|
|
int Offset = 0;
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// The current line's indent.
|
2015-05-12 17:23:57 +08:00
|
|
|
unsigned Indent = 0;
|
|
|
|
};
|
|
|
|
|
2017-06-14 20:29:47 +08:00
|
|
|
bool isNamespaceDeclaration(const AnnotatedLine *Line) {
|
|
|
|
const FormatToken *NamespaceTok = Line->First;
|
clang-format: add options to merge empty record body
Summary:
This patch introduces a few extra BraceWrapping options, similar to
`SplitEmptyFunction`, to allow merging empty 'record' bodies (e.g.
class, struct, union and namespace):
* SplitEmptyClass
* SplitEmptyStruct
* SplitEmptyUnion
* SplitEmptyNamespace
The `SplitEmptyFunction` option name has also been simplified/
shortened (from `SplitEmptyFunctionBody`).
These options are helpful when the correspond AfterXXX option is
enabled, to allow merging the empty record:
class Foo
{};
In addition, this fixes an unexpected merging of short records, when
the AfterXXXX options are used, which caused to be formatted like
this:
class Foo
{ void Foo(); };
This is now properly formatted as:
class Foo
{
void Foo();
};
Reviewers: djasper, krasimir
Reviewed By: djasper
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D34395
llvm-svn: 306874
2017-07-01 04:25:55 +08:00
|
|
|
return NamespaceTok && NamespaceTok->getNamespaceToken();
|
2017-06-14 20:29:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isEndOfNamespace(const AnnotatedLine *Line,
|
|
|
|
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
|
|
|
|
if (!Line->startsWith(tok::r_brace))
|
|
|
|
return false;
|
|
|
|
size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex;
|
|
|
|
if (StartLineIndex == UnwrappedLine::kInvalidIndex)
|
|
|
|
return false;
|
|
|
|
assert(StartLineIndex < AnnotatedLines.size());
|
|
|
|
return isNamespaceDeclaration(AnnotatedLines[StartLineIndex]);
|
|
|
|
}
|
|
|
|
|
2014-12-11 03:00:42 +08:00
|
|
|
class LineJoiner {
|
|
|
|
public:
|
2015-05-12 17:23:57 +08:00
|
|
|
LineJoiner(const FormatStyle &Style, const AdditionalKeywords &Keywords,
|
|
|
|
const SmallVectorImpl<AnnotatedLine *> &Lines)
|
2017-06-14 20:29:47 +08:00
|
|
|
: Style(Style), Keywords(Keywords), End(Lines.end()), Next(Lines.begin()),
|
|
|
|
AnnotatedLines(Lines) {}
|
2015-05-12 17:23:57 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Returns the next line, merging multiple lines into one if possible.
|
2015-05-12 17:23:57 +08:00
|
|
|
const AnnotatedLine *getNextMergedLine(bool DryRun,
|
|
|
|
LevelIndentTracker &IndentTracker) {
|
|
|
|
if (Next == End)
|
|
|
|
return nullptr;
|
|
|
|
const AnnotatedLine *Current = *Next;
|
|
|
|
IndentTracker.nextLine(*Current);
|
2017-09-20 17:51:03 +08:00
|
|
|
unsigned MergedLines = tryFitMultipleLinesInOne(IndentTracker, Next, End);
|
2015-05-12 17:23:57 +08:00
|
|
|
if (MergedLines > 0 && Style.ColumnLimit == 0)
|
|
|
|
// Disallow line merging if there is a break at the start of one of the
|
|
|
|
// input lines.
|
|
|
|
for (unsigned i = 0; i < MergedLines; ++i)
|
|
|
|
if (Next[i + 1]->First->NewlinesBefore > 0)
|
|
|
|
MergedLines = 0;
|
|
|
|
if (!DryRun)
|
|
|
|
for (unsigned i = 0; i < MergedLines; ++i)
|
2016-11-15 23:07:07 +08:00
|
|
|
join(*Next[0], *Next[i + 1]);
|
2015-05-12 17:23:57 +08:00
|
|
|
Next = Next + MergedLines + 1;
|
|
|
|
return Current;
|
|
|
|
}
|
2014-12-11 03:00:42 +08:00
|
|
|
|
2015-05-12 17:23:57 +08:00
|
|
|
private:
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Calculates how many lines can be merged into 1 starting at \p I.
|
2014-12-11 03:00:42 +08:00
|
|
|
unsigned
|
2017-06-14 20:29:47 +08:00
|
|
|
tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,
|
2014-12-11 03:00:42 +08:00
|
|
|
SmallVectorImpl<AnnotatedLine *>::const_iterator I,
|
|
|
|
SmallVectorImpl<AnnotatedLine *>::const_iterator E) {
|
2017-06-14 20:29:47 +08:00
|
|
|
const unsigned Indent = IndentTracker.getIndent();
|
|
|
|
|
2015-03-13 21:32:11 +08:00
|
|
|
// Can't join the last line with anything.
|
|
|
|
if (I + 1 == E)
|
|
|
|
return 0;
|
2014-12-11 03:00:42 +08:00
|
|
|
// We can never merge stuff if there are trailing line comments.
|
|
|
|
const AnnotatedLine *TheLine = *I;
|
|
|
|
if (TheLine->Last->is(TT_LineComment))
|
|
|
|
return 0;
|
2015-03-13 21:32:11 +08:00
|
|
|
if (I[1]->Type == LT_Invalid || I[1]->First->MustBreakBefore)
|
|
|
|
return 0;
|
|
|
|
if (TheLine->InPPDirective &&
|
|
|
|
(!I[1]->InPPDirective || I[1]->First->HasUnescapedNewline))
|
|
|
|
return 0;
|
2014-12-11 03:00:42 +08:00
|
|
|
|
|
|
|
if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
unsigned Limit =
|
|
|
|
Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent;
|
|
|
|
// If we already exceed the column limit, we set 'Limit' to 0. The different
|
|
|
|
// tryMerge..() functions can then decide whether to still do merging.
|
|
|
|
Limit = TheLine->Last->TotalLength > Limit
|
|
|
|
? 0
|
|
|
|
: Limit - TheLine->Last->TotalLength;
|
|
|
|
|
2017-06-13 15:02:43 +08:00
|
|
|
if (TheLine->Last->is(TT_FunctionLBrace) &&
|
|
|
|
TheLine->First == TheLine->Last &&
|
clang-format: add options to merge empty record body
Summary:
This patch introduces a few extra BraceWrapping options, similar to
`SplitEmptyFunction`, to allow merging empty 'record' bodies (e.g.
class, struct, union and namespace):
* SplitEmptyClass
* SplitEmptyStruct
* SplitEmptyUnion
* SplitEmptyNamespace
The `SplitEmptyFunction` option name has also been simplified/
shortened (from `SplitEmptyFunctionBody`).
These options are helpful when the correspond AfterXXX option is
enabled, to allow merging the empty record:
class Foo
{};
In addition, this fixes an unexpected merging of short records, when
the AfterXXXX options are used, which caused to be formatted like
this:
class Foo
{ void Foo(); };
This is now properly formatted as:
class Foo
{
void Foo();
};
Reviewers: djasper, krasimir
Reviewed By: djasper
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D34395
llvm-svn: 306874
2017-07-01 04:25:55 +08:00
|
|
|
!Style.BraceWrapping.SplitEmptyFunction &&
|
2017-06-13 15:02:43 +08:00
|
|
|
I[1]->First->is(tok::r_brace))
|
|
|
|
return tryMergeSimpleBlock(I, E, Limit);
|
|
|
|
|
clang-format: add options to merge empty record body
Summary:
This patch introduces a few extra BraceWrapping options, similar to
`SplitEmptyFunction`, to allow merging empty 'record' bodies (e.g.
class, struct, union and namespace):
* SplitEmptyClass
* SplitEmptyStruct
* SplitEmptyUnion
* SplitEmptyNamespace
The `SplitEmptyFunction` option name has also been simplified/
shortened (from `SplitEmptyFunctionBody`).
These options are helpful when the correspond AfterXXX option is
enabled, to allow merging the empty record:
class Foo
{};
In addition, this fixes an unexpected merging of short records, when
the AfterXXXX options are used, which caused to be formatted like
this:
class Foo
{ void Foo(); };
This is now properly formatted as:
class Foo
{
void Foo();
};
Reviewers: djasper, krasimir
Reviewed By: djasper
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D34395
llvm-svn: 306874
2017-07-01 04:25:55 +08:00
|
|
|
// Handle empty record blocks where the brace has already been wrapped
|
|
|
|
if (TheLine->Last->is(tok::l_brace) && TheLine->First == TheLine->Last &&
|
|
|
|
I != AnnotatedLines.begin()) {
|
|
|
|
bool EmptyBlock = I[1]->First->is(tok::r_brace);
|
|
|
|
|
|
|
|
const FormatToken *Tok = I[-1]->First;
|
|
|
|
if (Tok && Tok->is(tok::comment))
|
|
|
|
Tok = Tok->getNextNonComment();
|
|
|
|
|
|
|
|
if (Tok && Tok->getNamespaceToken())
|
|
|
|
return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock
|
2017-09-20 17:51:03 +08:00
|
|
|
? tryMergeSimpleBlock(I, E, Limit)
|
|
|
|
: 0;
|
clang-format: add options to merge empty record body
Summary:
This patch introduces a few extra BraceWrapping options, similar to
`SplitEmptyFunction`, to allow merging empty 'record' bodies (e.g.
class, struct, union and namespace):
* SplitEmptyClass
* SplitEmptyStruct
* SplitEmptyUnion
* SplitEmptyNamespace
The `SplitEmptyFunction` option name has also been simplified/
shortened (from `SplitEmptyFunctionBody`).
These options are helpful when the correspond AfterXXX option is
enabled, to allow merging the empty record:
class Foo
{};
In addition, this fixes an unexpected merging of short records, when
the AfterXXXX options are used, which caused to be formatted like
this:
class Foo
{ void Foo(); };
This is now properly formatted as:
class Foo
{
void Foo();
};
Reviewers: djasper, krasimir
Reviewed By: djasper
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D34395
llvm-svn: 306874
2017-07-01 04:25:55 +08:00
|
|
|
|
|
|
|
if (Tok && Tok->is(tok::kw_typedef))
|
|
|
|
Tok = Tok->getNextNonComment();
|
|
|
|
if (Tok && Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,
|
2017-09-15 19:23:50 +08:00
|
|
|
tok::kw_extern, Keywords.kw_interface))
|
clang-format: add options to merge empty record body
Summary:
This patch introduces a few extra BraceWrapping options, similar to
`SplitEmptyFunction`, to allow merging empty 'record' bodies (e.g.
class, struct, union and namespace):
* SplitEmptyClass
* SplitEmptyStruct
* SplitEmptyUnion
* SplitEmptyNamespace
The `SplitEmptyFunction` option name has also been simplified/
shortened (from `SplitEmptyFunctionBody`).
These options are helpful when the correspond AfterXXX option is
enabled, to allow merging the empty record:
class Foo
{};
In addition, this fixes an unexpected merging of short records, when
the AfterXXXX options are used, which caused to be formatted like
this:
class Foo
{ void Foo(); };
This is now properly formatted as:
class Foo
{
void Foo();
};
Reviewers: djasper, krasimir
Reviewed By: djasper
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D34395
llvm-svn: 306874
2017-07-01 04:25:55 +08:00
|
|
|
return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
|
2017-09-15 19:23:50 +08:00
|
|
|
? tryMergeSimpleBlock(I, E, Limit)
|
|
|
|
: 0;
|
clang-format: add options to merge empty record body
Summary:
This patch introduces a few extra BraceWrapping options, similar to
`SplitEmptyFunction`, to allow merging empty 'record' bodies (e.g.
class, struct, union and namespace):
* SplitEmptyClass
* SplitEmptyStruct
* SplitEmptyUnion
* SplitEmptyNamespace
The `SplitEmptyFunction` option name has also been simplified/
shortened (from `SplitEmptyFunctionBody`).
These options are helpful when the correspond AfterXXX option is
enabled, to allow merging the empty record:
class Foo
{};
In addition, this fixes an unexpected merging of short records, when
the AfterXXXX options are used, which caused to be formatted like
this:
class Foo
{ void Foo(); };
This is now properly formatted as:
class Foo
{
void Foo();
};
Reviewers: djasper, krasimir
Reviewed By: djasper
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D34395
llvm-svn: 306874
2017-07-01 04:25:55 +08:00
|
|
|
}
|
|
|
|
|
2014-12-11 03:00:42 +08:00
|
|
|
// FIXME: TheLine->Level != 0 might or might not be the right check to do.
|
|
|
|
// If necessary, change to something smarter.
|
|
|
|
bool MergeShortFunctions =
|
|
|
|
Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All ||
|
2015-06-11 21:31:45 +08:00
|
|
|
(Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
|
2014-12-11 03:00:42 +08:00
|
|
|
I[1]->First->is(tok::r_brace)) ||
|
2017-06-21 21:56:02 +08:00
|
|
|
(Style.AllowShortFunctionsOnASingleLine & FormatStyle::SFS_InlineOnly &&
|
2014-12-11 03:00:42 +08:00
|
|
|
TheLine->Level != 0);
|
|
|
|
|
2017-06-14 20:29:47 +08:00
|
|
|
if (Style.CompactNamespaces) {
|
|
|
|
if (isNamespaceDeclaration(TheLine)) {
|
|
|
|
int i = 0;
|
2018-04-23 17:34:26 +08:00
|
|
|
unsigned closingLine = TheLine->MatchingClosingBlockLineIndex - 1;
|
2017-06-14 20:29:47 +08:00
|
|
|
for (; I + 1 + i != E && isNamespaceDeclaration(I[i + 1]) &&
|
2018-04-23 17:34:26 +08:00
|
|
|
closingLine == I[i + 1]->MatchingClosingBlockLineIndex &&
|
2017-06-14 20:29:47 +08:00
|
|
|
I[i + 1]->Last->TotalLength < Limit;
|
|
|
|
i++, closingLine--) {
|
|
|
|
// No extra indent for compacted namespaces
|
|
|
|
IndentTracker.skipLine(*I[i + 1]);
|
|
|
|
|
|
|
|
Limit -= I[i + 1]->Last->TotalLength;
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isEndOfNamespace(TheLine, AnnotatedLines)) {
|
|
|
|
int i = 0;
|
|
|
|
unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1;
|
|
|
|
for (; I + 1 + i != E && isEndOfNamespace(I[i + 1], AnnotatedLines) &&
|
|
|
|
openingLine == I[i + 1]->MatchingOpeningBlockLineIndex;
|
|
|
|
i++, openingLine--) {
|
|
|
|
// No space between consecutive braces
|
|
|
|
I[i + 1]->First->SpacesRequiredBefore = !I[i]->Last->is(tok::r_brace);
|
|
|
|
|
|
|
|
// Indent like the outer-most namespace
|
|
|
|
IndentTracker.nextLine(*I[i + 1]);
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
// Try to merge a function block with left brace unwrapped
|
2014-12-11 03:00:42 +08:00
|
|
|
if (TheLine->Last->is(TT_FunctionLBrace) &&
|
|
|
|
TheLine->First != TheLine->Last) {
|
|
|
|
return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
|
|
|
|
}
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
// Try to merge a control statement block with left brace unwrapped
|
|
|
|
if (TheLine->Last->is(tok::l_brace) && TheLine->First != TheLine->Last &&
|
|
|
|
TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) {
|
|
|
|
return Style.AllowShortBlocksOnASingleLine
|
|
|
|
? tryMergeSimpleBlock(I, E, Limit)
|
|
|
|
: 0;
|
|
|
|
}
|
|
|
|
// Try to merge a control statement block with left brace wrapped
|
|
|
|
if (I[1]->First->is(tok::l_brace) &&
|
|
|
|
TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) {
|
|
|
|
return Style.BraceWrapping.AfterControlStatement
|
|
|
|
? tryMergeSimpleBlock(I, E, Limit)
|
|
|
|
: 0;
|
|
|
|
}
|
|
|
|
// Try to merge either empty or one-line block if is precedeed by control
|
|
|
|
// statement token
|
|
|
|
if (TheLine->First->is(tok::l_brace) && TheLine->First == TheLine->Last &&
|
|
|
|
I != AnnotatedLines.begin() &&
|
|
|
|
I[-1]->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) {
|
2018-01-20 00:12:37 +08:00
|
|
|
unsigned MergedLines = 0;
|
|
|
|
if (Style.AllowShortBlocksOnASingleLine) {
|
|
|
|
MergedLines = tryMergeSimpleBlock(I - 1, E, Limit);
|
|
|
|
// If we managed to merge the block, discard the first merged line
|
|
|
|
// since we are merging starting from I.
|
|
|
|
if (MergedLines > 0)
|
|
|
|
--MergedLines;
|
|
|
|
}
|
|
|
|
return MergedLines;
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
}
|
2018-02-27 21:48:27 +08:00
|
|
|
// Don't merge block with left brace wrapped after ObjC special blocks
|
|
|
|
if (TheLine->First->is(tok::l_brace) && I != AnnotatedLines.begin() &&
|
|
|
|
I[-1]->First->is(tok::at) && I[-1]->First->Next) {
|
|
|
|
tok::ObjCKeywordKind kwId = I[-1]->First->Next->Tok.getObjCKeywordID();
|
|
|
|
if (kwId == clang::tok::objc_autoreleasepool ||
|
|
|
|
kwId == clang::tok::objc_synchronized)
|
|
|
|
return 0;
|
|
|
|
}
|
2018-09-13 15:27:15 +08:00
|
|
|
// Don't merge block with left brace wrapped after case labels
|
|
|
|
if (TheLine->First->is(tok::l_brace) && I != AnnotatedLines.begin() &&
|
|
|
|
I[-1]->First->isOneOf(tok::kw_case, tok::kw_default))
|
|
|
|
return 0;
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
// Try to merge a block with left brace wrapped that wasn't yet covered
|
2014-12-11 03:00:42 +08:00
|
|
|
if (TheLine->Last->is(tok::l_brace)) {
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
return !Style.BraceWrapping.AfterFunction ||
|
2017-09-20 17:51:03 +08:00
|
|
|
(I[1]->First->is(tok::r_brace) &&
|
|
|
|
!Style.BraceWrapping.SplitEmptyRecord)
|
2014-12-11 03:00:42 +08:00
|
|
|
? tryMergeSimpleBlock(I, E, Limit)
|
|
|
|
: 0;
|
|
|
|
}
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
// Try to merge a function block with left brace wrapped
|
2014-12-11 03:00:42 +08:00
|
|
|
if (I[1]->First->is(TT_FunctionLBrace) &&
|
2015-09-29 22:57:55 +08:00
|
|
|
Style.BraceWrapping.AfterFunction) {
|
2014-12-11 03:00:42 +08:00
|
|
|
if (I[1]->Last->is(TT_LineComment))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Check for Limit <= 2 to account for the " {".
|
|
|
|
if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))
|
|
|
|
return 0;
|
|
|
|
Limit -= 2;
|
|
|
|
|
|
|
|
unsigned MergedLines = 0;
|
2017-06-13 15:02:43 +08:00
|
|
|
if (MergeShortFunctions ||
|
|
|
|
(Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
|
|
|
|
I[1]->First == I[1]->Last && I + 2 != E &&
|
|
|
|
I[2]->First->is(tok::r_brace))) {
|
2014-12-11 03:00:42 +08:00
|
|
|
MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
|
|
|
|
// If we managed to merge the block, count the function header, which is
|
|
|
|
// on a separate line.
|
|
|
|
if (MergedLines > 0)
|
|
|
|
++MergedLines;
|
|
|
|
}
|
|
|
|
return MergedLines;
|
|
|
|
}
|
|
|
|
if (TheLine->First->is(tok::kw_if)) {
|
|
|
|
return Style.AllowShortIfStatementsOnASingleLine
|
|
|
|
? tryMergeSimpleControlStatement(I, E, Limit)
|
|
|
|
: 0;
|
|
|
|
}
|
|
|
|
if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while)) {
|
|
|
|
return Style.AllowShortLoopsOnASingleLine
|
|
|
|
? tryMergeSimpleControlStatement(I, E, Limit)
|
|
|
|
: 0;
|
|
|
|
}
|
|
|
|
if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) {
|
|
|
|
return Style.AllowShortCaseLabelsOnASingleLine
|
|
|
|
? tryMergeShortCaseLabels(I, E, Limit)
|
|
|
|
: 0;
|
|
|
|
}
|
|
|
|
if (TheLine->InPPDirective &&
|
|
|
|
(TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {
|
|
|
|
return tryMergeSimplePPDirective(I, E, Limit);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
|
|
|
|
SmallVectorImpl<AnnotatedLine *>::const_iterator E,
|
|
|
|
unsigned Limit) {
|
|
|
|
if (Limit == 0)
|
|
|
|
return 0;
|
|
|
|
if (I + 2 != E && I[2]->InPPDirective && !I[2]->First->HasUnescapedNewline)
|
|
|
|
return 0;
|
|
|
|
if (1 + I[1]->Last->TotalLength > Limit)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned tryMergeSimpleControlStatement(
|
|
|
|
SmallVectorImpl<AnnotatedLine *>::const_iterator I,
|
|
|
|
SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
|
|
|
|
if (Limit == 0)
|
|
|
|
return 0;
|
2015-09-29 22:57:55 +08:00
|
|
|
if (Style.BraceWrapping.AfterControlStatement &&
|
2014-12-11 03:00:42 +08:00
|
|
|
(I[1]->First->is(tok::l_brace) && !Style.AllowShortBlocksOnASingleLine))
|
|
|
|
return 0;
|
|
|
|
if (I[1]->InPPDirective != (*I)->InPPDirective ||
|
|
|
|
(I[1]->InPPDirective && I[1]->First->HasUnescapedNewline))
|
|
|
|
return 0;
|
|
|
|
Limit = limitConsideringMacros(I + 1, E, Limit);
|
|
|
|
AnnotatedLine &Line = **I;
|
|
|
|
if (Line.Last->isNot(tok::r_paren))
|
|
|
|
return 0;
|
|
|
|
if (1 + I[1]->Last->TotalLength > Limit)
|
|
|
|
return 0;
|
2015-05-11 16:21:35 +08:00
|
|
|
if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while,
|
|
|
|
TT_LineComment))
|
2014-12-11 03:00:42 +08:00
|
|
|
return 0;
|
|
|
|
// Only inline simple if's (no nested if or else).
|
2015-06-17 17:43:56 +08:00
|
|
|
if (I + 2 != E && Line.startsWith(tok::kw_if) &&
|
2014-12-11 03:00:42 +08:00
|
|
|
I[2]->First->is(tok::kw_else))
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-05-11 16:21:35 +08:00
|
|
|
unsigned
|
|
|
|
tryMergeShortCaseLabels(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
|
|
|
|
SmallVectorImpl<AnnotatedLine *>::const_iterator E,
|
|
|
|
unsigned Limit) {
|
2014-12-11 03:00:42 +08:00
|
|
|
if (Limit == 0 || I + 1 == E ||
|
|
|
|
I[1]->First->isOneOf(tok::kw_case, tok::kw_default))
|
|
|
|
return 0;
|
2018-09-21 11:46:36 +08:00
|
|
|
if (I[0]->Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace))
|
|
|
|
return 0;
|
2014-12-11 03:00:42 +08:00
|
|
|
unsigned NumStmts = 0;
|
|
|
|
unsigned Length = 0;
|
2017-07-28 15:56:18 +08:00
|
|
|
bool EndsWithComment = false;
|
2014-12-11 03:00:42 +08:00
|
|
|
bool InPPDirective = I[0]->InPPDirective;
|
2017-07-28 15:56:18 +08:00
|
|
|
const unsigned Level = I[0]->Level;
|
2014-12-11 03:00:42 +08:00
|
|
|
for (; NumStmts < 3; ++NumStmts) {
|
|
|
|
if (I + 1 + NumStmts == E)
|
|
|
|
break;
|
|
|
|
const AnnotatedLine *Line = I[1 + NumStmts];
|
|
|
|
if (Line->InPPDirective != InPPDirective)
|
|
|
|
break;
|
|
|
|
if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
|
|
|
|
break;
|
|
|
|
if (Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,
|
2017-07-28 15:56:18 +08:00
|
|
|
tok::kw_while) ||
|
|
|
|
EndsWithComment)
|
2014-12-11 03:00:42 +08:00
|
|
|
return 0;
|
2017-07-28 15:56:18 +08:00
|
|
|
if (Line->First->is(tok::comment)) {
|
|
|
|
if (Level != Line->Level)
|
|
|
|
return 0;
|
|
|
|
SmallVectorImpl<AnnotatedLine *>::const_iterator J = I + 2 + NumStmts;
|
|
|
|
for (; J != E; ++J) {
|
|
|
|
Line = *J;
|
|
|
|
if (Line->InPPDirective != InPPDirective)
|
|
|
|
break;
|
|
|
|
if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
|
|
|
|
break;
|
|
|
|
if (Line->First->isNot(tok::comment) || Level != Line->Level)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Line->Last->is(tok::comment))
|
|
|
|
EndsWithComment = true;
|
2014-12-11 03:00:42 +08:00
|
|
|
Length += I[1 + NumStmts]->Last->TotalLength + 1; // 1 for the space.
|
|
|
|
}
|
|
|
|
if (NumStmts == 0 || NumStmts == 3 || Length > Limit)
|
|
|
|
return 0;
|
|
|
|
return NumStmts;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
|
|
|
|
SmallVectorImpl<AnnotatedLine *>::const_iterator E,
|
|
|
|
unsigned Limit) {
|
|
|
|
AnnotatedLine &Line = **I;
|
|
|
|
|
|
|
|
// Don't merge ObjC @ keywords and methods.
|
2015-02-07 09:57:32 +08:00
|
|
|
// FIXME: If an option to allow short exception handling clauses on a single
|
|
|
|
// line is added, change this to not return for @try and friends.
|
2014-12-11 03:00:42 +08:00
|
|
|
if (Style.Language != FormatStyle::LK_Java &&
|
|
|
|
Line.First->isOneOf(tok::at, tok::minus, tok::plus))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Check that the current line allows merging. This depends on whether we
|
|
|
|
// are in a control flow statements as well as several style flags.
|
2015-04-30 17:24:17 +08:00
|
|
|
if (Line.First->isOneOf(tok::kw_else, tok::kw_case) ||
|
2017-10-02 23:53:37 +08:00
|
|
|
(Line.First->Next && Line.First->Next->is(tok::kw_else)))
|
2014-12-11 03:00:42 +08:00
|
|
|
return 0;
|
2018-09-02 17:04:51 +08:00
|
|
|
// default: in switch statement
|
|
|
|
if (Line.First->is(tok::kw_default)) {
|
|
|
|
const FormatToken *Tok = Line.First->getNextNonComment();
|
|
|
|
if (Tok && Tok->is(tok::colon))
|
|
|
|
return 0;
|
|
|
|
}
|
2014-12-11 03:00:42 +08:00
|
|
|
if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try,
|
2015-02-04 23:26:27 +08:00
|
|
|
tok::kw___try, tok::kw_catch, tok::kw___finally,
|
2015-06-17 17:43:56 +08:00
|
|
|
tok::kw_for, tok::r_brace, Keywords.kw___except)) {
|
2014-12-11 03:00:42 +08:00
|
|
|
if (!Style.AllowShortBlocksOnASingleLine)
|
|
|
|
return 0;
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
// Don't merge when we can't except the case when
|
|
|
|
// the control statement block is empty
|
|
|
|
if (!Style.AllowShortIfStatementsOnASingleLine &&
|
|
|
|
Line.startsWith(tok::kw_if) &&
|
|
|
|
!Style.BraceWrapping.AfterControlStatement &&
|
|
|
|
!I[1]->First->is(tok::r_brace))
|
|
|
|
return 0;
|
2014-12-11 03:00:42 +08:00
|
|
|
if (!Style.AllowShortIfStatementsOnASingleLine &&
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
Line.startsWith(tok::kw_if) &&
|
|
|
|
Style.BraceWrapping.AfterControlStatement && I + 2 != E &&
|
|
|
|
!I[2]->First->is(tok::r_brace))
|
2014-12-11 03:00:42 +08:00
|
|
|
return 0;
|
|
|
|
if (!Style.AllowShortLoopsOnASingleLine &&
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) &&
|
|
|
|
!Style.BraceWrapping.AfterControlStatement &&
|
|
|
|
!I[1]->First->is(tok::r_brace))
|
|
|
|
return 0;
|
|
|
|
if (!Style.AllowShortLoopsOnASingleLine &&
|
|
|
|
Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) &&
|
|
|
|
Style.BraceWrapping.AfterControlStatement && I + 2 != E &&
|
|
|
|
!I[2]->First->is(tok::r_brace))
|
2014-12-11 03:00:42 +08:00
|
|
|
return 0;
|
|
|
|
// FIXME: Consider an option to allow short exception handling clauses on
|
|
|
|
// a single line.
|
2015-02-04 23:26:27 +08:00
|
|
|
// FIXME: This isn't covered by tests.
|
|
|
|
// FIXME: For catch, __except, __finally the first token on the line
|
|
|
|
// is '}', so this isn't correct here.
|
|
|
|
if (Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
|
|
|
|
Keywords.kw___except, tok::kw___finally))
|
2014-12-11 03:00:42 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
if (Line.Last->is(tok::l_brace)) {
|
|
|
|
FormatToken *Tok = I[1]->First;
|
|
|
|
if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&
|
|
|
|
(Tok->getNextNonComment() == nullptr ||
|
|
|
|
Tok->getNextNonComment()->is(tok::semi))) {
|
|
|
|
// We merge empty blocks even if the line exceeds the column limit.
|
|
|
|
Tok->SpacesRequiredBefore = 0;
|
|
|
|
Tok->CanBreakBefore = true;
|
|
|
|
return 1;
|
2018-09-05 15:44:02 +08:00
|
|
|
} else if (Limit != 0 && !Line.startsWithNamespace() &&
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
!startsExternCBlock(Line)) {
|
|
|
|
// We don't merge short records.
|
2017-11-25 17:35:33 +08:00
|
|
|
FormatToken *RecordTok = Line.First;
|
|
|
|
// Skip record modifiers.
|
|
|
|
while (RecordTok->Next &&
|
|
|
|
RecordTok->isOneOf(tok::kw_typedef, tok::kw_export,
|
|
|
|
Keywords.kw_declare, Keywords.kw_abstract,
|
|
|
|
tok::kw_default))
|
|
|
|
RecordTok = RecordTok->Next;
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
if (RecordTok &&
|
|
|
|
RecordTok->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct,
|
|
|
|
Keywords.kw_interface))
|
|
|
|
return 0;
|
2014-12-11 03:00:42 +08:00
|
|
|
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
// Check that we still have three lines and they fit into the limit.
|
|
|
|
if (I + 2 == E || I[2]->Type == LT_Invalid)
|
|
|
|
return 0;
|
|
|
|
Limit = limitConsideringMacros(I + 2, E, Limit);
|
2014-12-11 03:00:42 +08:00
|
|
|
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
if (!nextTwoLinesFitInto(I, Limit))
|
|
|
|
return 0;
|
2014-12-11 03:00:42 +08:00
|
|
|
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
// Second, check that the next line does not contain any braces - if it
|
|
|
|
// does, readability declines when putting it into a single line.
|
|
|
|
if (I[1]->Last->is(TT_LineComment))
|
2014-12-11 03:00:42 +08:00
|
|
|
return 0;
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
do {
|
|
|
|
if (Tok->is(tok::l_brace) && Tok->BlockKind != BK_BracedInit)
|
|
|
|
return 0;
|
|
|
|
Tok = Tok->Next;
|
|
|
|
} while (Tok);
|
2014-12-11 03:00:42 +08:00
|
|
|
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
// Last, check that the third line starts with a closing brace.
|
|
|
|
Tok = I[2]->First;
|
|
|
|
if (Tok->isNot(tok::r_brace))
|
|
|
|
return 0;
|
2014-12-11 03:00:42 +08:00
|
|
|
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
// Don't merge "if (a) { .. } else {".
|
|
|
|
if (Tok->Next && Tok->Next->is(tok::kw_else))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
} else if (I[1]->First->is(tok::l_brace)) {
|
|
|
|
if (I[1]->Last->is(TT_LineComment))
|
2015-04-30 17:24:17 +08:00
|
|
|
return 0;
|
|
|
|
|
[clang-format] Fixed one-line if statement
Summary:
**Short overview:**
Fixed bug: https://bugs.llvm.org/show_bug.cgi?id=34001
Clang-format bug resulting in a strange behavior of control statements short blocks. Different flags combinations do not guarantee expected result. Turned on option AllowShortBlocksOnASingleLine does not work as intended.
**Description of the problem:**
Cpp source file UnwrappedLineFormatter does not handle AllowShortBlocksOnASingleLine flag as it should. Putting a single-line control statement without any braces, clang-format works as expected (depending on AllowShortIfStatementOnASingleLine or AllowShortLoopsOnASingleLine value). Putting a single-line control statement in braces, we can observe strange and incorrect behavior.
Our short block is intercepted by tryFitMultipleLinesInOne function. The function returns a number of lines to be merged. Unfortunately, our control statement block is not covered properly. There are several if-return statements, but none of them handles our block. A block is identified by the line first token and by left and right braces. A function block works as expected, there is such an if-return statement doing proper job. A control statement block, from the other hand, falls into strange conditional construct, which depends on BraceWrapping.AfterFunction flag (with condition that the line’s last token is left brace, what is possible in our case) or goes even further. That should definitely not happen.
**Description of the patch:**
By adding three different if statements, we guarantee that our short control statement block, however it looks like (different brace wrapping flags may be turned on), is handled properly and does not fall into wrong conditional construct. Depending on appropriate options we return either 0 (when something disturbs our merging attempt) or let another function (tryMergeSimpleBlock) take the responsibility of returned result (number of merged lines). Nevertheless, one more correction is required in mentioned tryMergeSimpleBlock function. The function, previously, returned either 0 or 2. The problem was that this did not handle the case when our block had the left brace in a separate line, not the header one. After change, after adding condition, we return the result compatible with block’s structure. In case of left brace in the header’s line we do everything as before the patch. In case of left brace in a separate line we do the job similar to the one we do in case of a “non-header left brace” function short block. To be precise, we try to merge the block ignoring the header line. Then, if success, we increment our returned result.
**After fix:**
**CONFIG:**
```
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
BreakBeforeBraces: Custom
BraceWrapping: {
AfterClass: true, AfterControlStatement: true, AfterEnum: true, AfterFunction: true, AfterNamespace: false, AfterStruct: true, AfterUnion: true, BeforeCatch: true, BeforeElse: true
}
```
**BEFORE:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) {
doSomething();
}
if (statement)
{
doSomething();
}
if (statement)
doSomething();
if (statement) {
doSomething1();
doSomething2();
}
```
**AFTER:**
```
if (statement) doSomething();
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) { doSomething(); }
if (statement) doSomething();
if (statement)
{
doSomething1();
doSomething2();
}
```
Contributed by @PriMee!
Reviewers: krasimir, djasper
Reviewed By: krasimir
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D37140
llvm-svn: 312904
2017-09-11 18:12:16 +08:00
|
|
|
// Check for Limit <= 2 to account for the " {".
|
|
|
|
if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I)))
|
|
|
|
return 0;
|
|
|
|
Limit -= 2;
|
|
|
|
unsigned MergedLines = 0;
|
|
|
|
if (Style.AllowShortBlocksOnASingleLine ||
|
|
|
|
(I[1]->First == I[1]->Last && I + 2 != E &&
|
|
|
|
I[2]->First->is(tok::r_brace))) {
|
|
|
|
MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
|
|
|
|
// If we managed to merge the block, count the statement header, which
|
|
|
|
// is on a separate line.
|
|
|
|
if (MergedLines > 0)
|
|
|
|
++MergedLines;
|
|
|
|
}
|
|
|
|
return MergedLines;
|
2014-12-11 03:00:42 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the modified column limit for \p I if it is inside a macro and
|
|
|
|
/// needs a trailing '\'.
|
|
|
|
unsigned
|
|
|
|
limitConsideringMacros(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
|
|
|
|
SmallVectorImpl<AnnotatedLine *>::const_iterator E,
|
|
|
|
unsigned Limit) {
|
|
|
|
if (I[0]->InPPDirective && I + 1 != E &&
|
|
|
|
!I[1]->First->HasUnescapedNewline && !I[1]->First->is(tok::eof)) {
|
|
|
|
return Limit < 2 ? 0 : Limit - 2;
|
|
|
|
}
|
|
|
|
return Limit;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
|
|
|
|
unsigned Limit) {
|
|
|
|
if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore)
|
|
|
|
return false;
|
|
|
|
return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool containsMustBreak(const AnnotatedLine *Line) {
|
|
|
|
for (const FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
|
|
|
|
if (Tok->MustBreakBefore)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-05-12 17:23:57 +08:00
|
|
|
void join(AnnotatedLine &A, const AnnotatedLine &B) {
|
|
|
|
assert(!A.Last->Next);
|
|
|
|
assert(!B.First->Previous);
|
|
|
|
if (B.Affected)
|
|
|
|
A.Affected = true;
|
|
|
|
A.Last->Next = B.First;
|
|
|
|
B.First->Previous = A.Last;
|
|
|
|
B.First->CanBreakBefore = true;
|
|
|
|
unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
|
|
|
|
for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) {
|
|
|
|
Tok->TotalLength += LengthA;
|
|
|
|
A.Last = Tok;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-11 03:00:42 +08:00
|
|
|
const FormatStyle &Style;
|
2015-02-04 23:26:27 +08:00
|
|
|
const AdditionalKeywords &Keywords;
|
2015-06-17 21:08:06 +08:00
|
|
|
const SmallVectorImpl<AnnotatedLine *>::const_iterator End;
|
2015-05-12 17:23:57 +08:00
|
|
|
|
2015-06-17 21:08:06 +08:00
|
|
|
SmallVectorImpl<AnnotatedLine *>::const_iterator Next;
|
2017-06-14 20:29:47 +08:00
|
|
|
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;
|
2014-12-11 03:00:42 +08:00
|
|
|
};
|
|
|
|
|
2015-05-11 16:21:35 +08:00
|
|
|
static void markFinalized(FormatToken *Tok) {
|
|
|
|
for (; Tok; Tok = Tok->Next) {
|
|
|
|
Tok->Finalized = true;
|
|
|
|
for (AnnotatedLine *Child : Tok->Children)
|
|
|
|
markFinalized(Child->First);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
static void printLineState(const LineState &State) {
|
|
|
|
llvm::dbgs() << "State: ";
|
|
|
|
for (const ParenState &P : State.Stack) {
|
2018-05-09 17:02:11 +08:00
|
|
|
llvm::dbgs() << (P.Tok ? P.Tok->TokenText : "F") << "|" << P.Indent << "|"
|
|
|
|
<< P.LastSpace << "|" << P.NestedBlockIndent << " ";
|
2015-05-11 16:21:35 +08:00
|
|
|
}
|
|
|
|
llvm::dbgs() << State.NextToken->TokenText << "\n";
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Base class for classes that format one \c AnnotatedLine.
|
2015-05-11 16:21:35 +08:00
|
|
|
class LineFormatter {
|
2014-12-11 03:00:42 +08:00
|
|
|
public:
|
2015-05-11 16:21:35 +08:00
|
|
|
LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,
|
|
|
|
const FormatStyle &Style,
|
|
|
|
UnwrappedLineFormatter *BlockFormatter)
|
|
|
|
: Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
|
|
|
|
BlockFormatter(BlockFormatter) {}
|
2015-10-20 21:23:58 +08:00
|
|
|
virtual ~LineFormatter() {}
|
2015-05-11 16:21:35 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Formats an \c AnnotatedLine and returns the penalty.
|
2015-05-11 16:21:35 +08:00
|
|
|
///
|
|
|
|
/// If \p DryRun is \c false, directly applies the changes.
|
2017-10-30 22:01:50 +08:00
|
|
|
virtual unsigned formatLine(const AnnotatedLine &Line,
|
|
|
|
unsigned FirstIndent,
|
|
|
|
unsigned FirstStartColumn,
|
2015-05-11 16:21:35 +08:00
|
|
|
bool DryRun) = 0;
|
|
|
|
|
|
|
|
protected:
|
2018-05-09 09:00:01 +08:00
|
|
|
/// If the \p State's next token is an r_brace closing a nested block,
|
2015-05-11 16:21:35 +08:00
|
|
|
/// format the nested block before it.
|
|
|
|
///
|
|
|
|
/// Returns \c true if all children could be placed successfully and adapts
|
|
|
|
/// \p Penalty as well as \p State. If \p DryRun is false, also directly
|
|
|
|
/// creates changes using \c Whitespaces.
|
|
|
|
///
|
|
|
|
/// The crucial idea here is that children always get formatted upon
|
|
|
|
/// encountering the closing brace right after the nested block. Now, if we
|
|
|
|
/// are currently trying to keep the "}" on the same line (i.e. \p NewLine is
|
|
|
|
/// \c false), the entire block has to be kept on the same line (which is only
|
|
|
|
/// possible if it fits on the line, only contains a single statement, etc.
|
|
|
|
///
|
|
|
|
/// If \p NewLine is true, we format the nested block on separate lines, i.e.
|
|
|
|
/// break after the "{", format all lines with correct indentation and the put
|
|
|
|
/// the closing "}" on yet another new line.
|
|
|
|
///
|
|
|
|
/// This enables us to keep the simple structure of the
|
|
|
|
/// \c UnwrappedLineFormatter, where we only have two options for each token:
|
|
|
|
/// break or don't break.
|
|
|
|
bool formatChildren(LineState &State, bool NewLine, bool DryRun,
|
|
|
|
unsigned &Penalty) {
|
|
|
|
const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
|
|
|
|
FormatToken &Previous = *State.NextToken->Previous;
|
|
|
|
if (!LBrace || LBrace->isNot(tok::l_brace) ||
|
|
|
|
LBrace->BlockKind != BK_Block || Previous.Children.size() == 0)
|
|
|
|
// The previous token does not open a block. Nothing to do. We don't
|
|
|
|
// assert so that we can simply call this function for all tokens.
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (NewLine) {
|
|
|
|
int AdditionalIndent = State.Stack.back().Indent -
|
|
|
|
Previous.Children[0]->Level * Style.IndentWidth;
|
|
|
|
|
|
|
|
Penalty +=
|
|
|
|
BlockFormatter->format(Previous.Children, DryRun, AdditionalIndent,
|
|
|
|
/*FixBadIndentation=*/true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Previous.Children[0]->First->MustBreakBefore)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Cannot merge into one line if this line ends on a comment.
|
|
|
|
if (Previous.is(tok::comment))
|
|
|
|
return false;
|
|
|
|
|
2017-01-31 19:25:01 +08:00
|
|
|
// Cannot merge multiple statements into a single line.
|
|
|
|
if (Previous.Children.size() > 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const AnnotatedLine *Child = Previous.Children[0];
|
2015-05-11 16:21:35 +08:00
|
|
|
// We can't put the closing "}" on a line with a trailing comment.
|
2017-01-31 19:25:01 +08:00
|
|
|
if (Child->Last->isTrailingComment())
|
2015-05-11 16:21:35 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// If the child line exceeds the column limit, we wouldn't want to merge it.
|
|
|
|
// We add +2 for the trailing " }".
|
|
|
|
if (Style.ColumnLimit > 0 &&
|
2017-01-31 19:25:01 +08:00
|
|
|
Child->Last->TotalLength + State.Column + 2 > Style.ColumnLimit)
|
2015-05-11 16:21:35 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!DryRun) {
|
|
|
|
Whitespaces->replaceWhitespace(
|
2017-01-31 19:25:01 +08:00
|
|
|
*Child->First, /*Newlines=*/0, /*Spaces=*/1,
|
2015-05-11 16:21:35 +08:00
|
|
|
/*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective);
|
|
|
|
}
|
2017-10-30 22:01:50 +08:00
|
|
|
Penalty +=
|
|
|
|
formatLine(*Child, State.Column + 1, /*FirstStartColumn=*/0, DryRun);
|
2015-05-11 16:21:35 +08:00
|
|
|
|
2017-01-31 19:25:01 +08:00
|
|
|
State.Column += 1 + Child->Last->TotalLength;
|
2015-05-11 16:21:35 +08:00
|
|
|
return true;
|
|
|
|
}
|
2014-12-11 03:00:42 +08:00
|
|
|
|
2015-05-11 16:21:35 +08:00
|
|
|
ContinuationIndenter *Indenter;
|
|
|
|
|
|
|
|
private:
|
|
|
|
WhitespaceManager *Whitespaces;
|
|
|
|
const FormatStyle &Style;
|
|
|
|
UnwrappedLineFormatter *BlockFormatter;
|
|
|
|
};
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Formatter that keeps the existing line breaks.
|
2015-05-11 16:21:35 +08:00
|
|
|
class NoColumnLimitLineFormatter : public LineFormatter {
|
|
|
|
public:
|
|
|
|
NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,
|
|
|
|
WhitespaceManager *Whitespaces,
|
|
|
|
const FormatStyle &Style,
|
|
|
|
UnwrappedLineFormatter *BlockFormatter)
|
|
|
|
: LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Formats the line, simply keeping all of the input's line breaking
|
2015-05-11 16:21:35 +08:00
|
|
|
/// decisions.
|
|
|
|
unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
|
2017-10-30 22:01:50 +08:00
|
|
|
unsigned FirstStartColumn, bool DryRun) override {
|
2015-05-11 16:21:35 +08:00
|
|
|
assert(!DryRun);
|
2017-10-30 22:01:50 +08:00
|
|
|
LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn,
|
|
|
|
&Line, /*DryRun=*/false);
|
2014-12-11 03:00:42 +08:00
|
|
|
while (State.NextToken) {
|
|
|
|
bool Newline =
|
|
|
|
Indenter->mustBreak(State) ||
|
|
|
|
(Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
|
2015-04-23 17:23:17 +08:00
|
|
|
unsigned Penalty = 0;
|
2015-05-11 16:21:35 +08:00
|
|
|
formatChildren(State, Newline, /*DryRun=*/false, Penalty);
|
2014-12-11 03:00:42 +08:00
|
|
|
Indenter->addTokenToState(State, Newline, /*DryRun=*/false);
|
|
|
|
}
|
2015-05-11 16:21:35 +08:00
|
|
|
return 0;
|
2014-12-11 03:00:42 +08:00
|
|
|
}
|
2015-05-11 16:21:35 +08:00
|
|
|
};
|
2014-12-11 03:00:42 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Formatter that puts all tokens into a single line without breaks.
|
2015-05-11 16:21:35 +08:00
|
|
|
class NoLineBreakFormatter : public LineFormatter {
|
|
|
|
public:
|
|
|
|
NoLineBreakFormatter(ContinuationIndenter *Indenter,
|
|
|
|
WhitespaceManager *Whitespaces, const FormatStyle &Style,
|
|
|
|
UnwrappedLineFormatter *BlockFormatter)
|
|
|
|
: LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Puts all tokens into a single line.
|
2015-05-11 16:21:35 +08:00
|
|
|
unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
|
2017-10-30 22:01:50 +08:00
|
|
|
unsigned FirstStartColumn, bool DryRun) override {
|
2015-05-11 16:21:35 +08:00
|
|
|
unsigned Penalty = 0;
|
2017-10-30 22:01:50 +08:00
|
|
|
LineState State =
|
|
|
|
Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun);
|
2015-05-11 16:21:35 +08:00
|
|
|
while (State.NextToken) {
|
|
|
|
formatChildren(State, /*Newline=*/false, DryRun, Penalty);
|
2017-05-18 16:07:52 +08:00
|
|
|
Indenter->addTokenToState(
|
|
|
|
State, /*Newline=*/State.NextToken->MustBreakBefore, DryRun);
|
2015-05-11 16:21:35 +08:00
|
|
|
}
|
|
|
|
return Penalty;
|
|
|
|
}
|
2014-12-11 03:00:42 +08:00
|
|
|
};
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Finds the best way to break lines.
|
2015-05-11 16:21:35 +08:00
|
|
|
class OptimizingLineFormatter : public LineFormatter {
|
|
|
|
public:
|
|
|
|
OptimizingLineFormatter(ContinuationIndenter *Indenter,
|
|
|
|
WhitespaceManager *Whitespaces,
|
|
|
|
const FormatStyle &Style,
|
|
|
|
UnwrappedLineFormatter *BlockFormatter)
|
|
|
|
: LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Formats the line by finding the best line breaks with line lengths
|
2015-05-11 16:21:35 +08:00
|
|
|
/// below the column limit.
|
|
|
|
unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
|
2017-10-30 22:01:50 +08:00
|
|
|
unsigned FirstStartColumn, bool DryRun) override {
|
|
|
|
LineState State =
|
|
|
|
Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun);
|
2015-05-11 16:21:35 +08:00
|
|
|
|
|
|
|
// If the ObjC method declaration does not fit on a line, we should format
|
|
|
|
// it with one arg per line.
|
|
|
|
if (State.Line->Type == LT_ObjCMethodDecl)
|
|
|
|
State.Stack.back().BreakBeforeParameter = true;
|
|
|
|
|
|
|
|
// Find best solution in solution space.
|
|
|
|
return analyzeSolutionSpace(State, DryRun);
|
|
|
|
}
|
2015-01-24 03:37:25 +08:00
|
|
|
|
2015-05-11 16:21:35 +08:00
|
|
|
private:
|
|
|
|
struct CompareLineStatePointers {
|
|
|
|
bool operator()(LineState *obj1, LineState *obj2) const {
|
|
|
|
return *obj1 < *obj2;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// A pair of <penalty, count> that is used to prioritize the BFS on.
|
2015-05-11 16:21:35 +08:00
|
|
|
///
|
|
|
|
/// In case of equal penalties, we want to prefer states that were inserted
|
|
|
|
/// first. During state generation we make sure that we insert states first
|
|
|
|
/// that break the line as late as possible.
|
|
|
|
typedef std::pair<unsigned, unsigned> OrderedPenalty;
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// An edge in the solution space from \c Previous->State to \c State,
|
2015-05-11 16:21:35 +08:00
|
|
|
/// inserting a newline dependent on the \c NewLine.
|
|
|
|
struct StateNode {
|
|
|
|
StateNode(const LineState &State, bool NewLine, StateNode *Previous)
|
|
|
|
: State(State), NewLine(NewLine), Previous(Previous) {}
|
|
|
|
LineState State;
|
|
|
|
bool NewLine;
|
|
|
|
StateNode *Previous;
|
|
|
|
};
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// An item in the prioritized BFS search queue. The \c StateNode's
|
2015-05-11 16:21:35 +08:00
|
|
|
/// \c State has the given \c OrderedPenalty.
|
|
|
|
typedef std::pair<OrderedPenalty, StateNode *> QueueItem;
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// The BFS queue type.
|
2015-05-11 16:21:35 +08:00
|
|
|
typedef std::priority_queue<QueueItem, std::vector<QueueItem>,
|
2017-09-20 17:51:03 +08:00
|
|
|
std::greater<QueueItem>>
|
|
|
|
QueueType;
|
2015-05-11 16:21:35 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Analyze the entire solution space starting from \p InitialState.
|
2015-05-11 16:21:35 +08:00
|
|
|
///
|
|
|
|
/// This implements a variant of Dijkstra's algorithm on the graph that spans
|
|
|
|
/// the solution space (\c LineStates are the nodes). The algorithm tries to
|
|
|
|
/// find the shortest path (the one with lowest penalty) from \p InitialState
|
|
|
|
/// to a state where all tokens are placed. Returns the penalty.
|
|
|
|
///
|
|
|
|
/// If \p DryRun is \c false, directly applies the changes.
|
|
|
|
unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun) {
|
|
|
|
std::set<LineState *, CompareLineStatePointers> Seen;
|
|
|
|
|
|
|
|
// Increasing count of \c StateNode items we have created. This is used to
|
|
|
|
// create a deterministic order independent of the container.
|
|
|
|
unsigned Count = 0;
|
|
|
|
QueueType Queue;
|
|
|
|
|
|
|
|
// Insert start element into queue.
|
|
|
|
StateNode *Node =
|
|
|
|
new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);
|
|
|
|
Queue.push(QueueItem(OrderedPenalty(0, Count), Node));
|
|
|
|
++Count;
|
|
|
|
|
|
|
|
unsigned Penalty = 0;
|
|
|
|
|
|
|
|
// While not empty, take first element and follow edges.
|
|
|
|
while (!Queue.empty()) {
|
|
|
|
Penalty = Queue.top().first.first;
|
|
|
|
StateNode *Node = Queue.top().second;
|
|
|
|
if (!Node->State.NextToken) {
|
2018-05-15 21:30:56 +08:00
|
|
|
LLVM_DEBUG(llvm::dbgs()
|
|
|
|
<< "\n---\nPenalty for line: " << Penalty << "\n");
|
2015-05-11 16:21:35 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
Queue.pop();
|
|
|
|
|
|
|
|
// Cut off the analysis of certain solutions if the analysis gets too
|
|
|
|
// complex. See description of IgnoreStackForComparison.
|
2015-10-28 06:55:55 +08:00
|
|
|
if (Count > 50000)
|
2015-05-11 16:21:35 +08:00
|
|
|
Node->State.IgnoreStackForComparison = true;
|
|
|
|
|
|
|
|
if (!Seen.insert(&Node->State).second)
|
|
|
|
// State already examined with lower penalty.
|
|
|
|
continue;
|
|
|
|
|
|
|
|
FormatDecision LastFormat = Node->State.NextToken->Decision;
|
|
|
|
if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)
|
|
|
|
addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);
|
|
|
|
if (LastFormat == FD_Unformatted || LastFormat == FD_Break)
|
|
|
|
addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Queue.empty()) {
|
|
|
|
// We were unable to find a solution, do nothing.
|
|
|
|
// FIXME: Add diagnostic?
|
2018-05-15 21:30:56 +08:00
|
|
|
LLVM_DEBUG(llvm::dbgs() << "Could not find a solution.\n");
|
2015-05-11 16:21:35 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reconstruct the solution.
|
|
|
|
if (!DryRun)
|
|
|
|
reconstructPath(InitialState, Queue.top().second);
|
|
|
|
|
2018-05-15 21:30:56 +08:00
|
|
|
LLVM_DEBUG(llvm::dbgs()
|
|
|
|
<< "Total number of analyzed states: " << Count << "\n");
|
|
|
|
LLVM_DEBUG(llvm::dbgs() << "---\n");
|
2015-05-11 16:21:35 +08:00
|
|
|
|
|
|
|
return Penalty;
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Add the following state to the analysis queue \c Queue.
|
2015-05-11 16:21:35 +08:00
|
|
|
///
|
|
|
|
/// Assume the current state is \p PreviousNode and has been reached with a
|
|
|
|
/// penalty of \p Penalty. Insert a line break if \p NewLine is \c true.
|
|
|
|
void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode,
|
|
|
|
bool NewLine, unsigned *Count, QueueType *Queue) {
|
|
|
|
if (NewLine && !Indenter->canBreak(PreviousNode->State))
|
|
|
|
return;
|
|
|
|
if (!NewLine && Indenter->mustBreak(PreviousNode->State))
|
|
|
|
return;
|
|
|
|
|
|
|
|
StateNode *Node = new (Allocator.Allocate())
|
|
|
|
StateNode(PreviousNode->State, NewLine, PreviousNode);
|
|
|
|
if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))
|
|
|
|
return;
|
|
|
|
|
|
|
|
Penalty += Indenter->addTokenToState(Node->State, NewLine, true);
|
|
|
|
|
|
|
|
Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
|
|
|
|
++(*Count);
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Applies the best formatting by reconstructing the path in the
|
2015-05-11 16:21:35 +08:00
|
|
|
/// solution space that leads to \c Best.
|
|
|
|
void reconstructPath(LineState &State, StateNode *Best) {
|
|
|
|
std::deque<StateNode *> Path;
|
|
|
|
// We do not need a break before the initial token.
|
|
|
|
while (Best->Previous) {
|
|
|
|
Path.push_front(Best);
|
|
|
|
Best = Best->Previous;
|
|
|
|
}
|
[clang-format] tweaked another case of lambda formatting
Summary:
This is done in order to improve cases where the lambda's body is moved too far to the right. Consider the following snippet with column limit set to 79:
```
void f() {
leader::MakeThisCallHere(&leader_service_,
cq_.get(),
[this, liveness](const leader::ReadRecordReq& req,
std::function<void()> done) {
logger_->HandleReadRecord(
req, resp, std::move(done));
});
leader::MakeAnother(&leader_service_,
cq_.get(),
[this, liveness](const leader::ReadRecordReq& req,
std::function<void()> done) {
logger_->HandleReadRecord(
req, resp, std::move(done), a);
});
}
```
The tool favors extra indentation for the lambda body and so the code incurs extra wrapping and adjacent calls are indented to a different level. I find this behavior annoying and I'd like the tool to favor new lines and, thus, use the extra width.
The fix, reduced, brings the following formatting.
Before:
function(1,
[] {
DoStuff();
//
},
1);
After:
function(
1,
[] {
DoStuff();
//
},
1);
Refer to the new tests in FormatTest.cpp
Contributed by oleg.smolsky!
Reviewers: djasper, klimek, krasimir
Subscribers: cfe-commits, owenpan
Tags: #clang
Differential Revision: https://reviews.llvm.org/D52676
llvm-svn: 345753
2018-11-01 01:56:57 +08:00
|
|
|
for (auto I = Path.begin(), E = Path.end(); I != E; ++I) {
|
2015-05-11 16:21:35 +08:00
|
|
|
unsigned Penalty = 0;
|
|
|
|
formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);
|
|
|
|
Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);
|
|
|
|
|
2018-05-15 21:30:56 +08:00
|
|
|
LLVM_DEBUG({
|
2015-05-11 16:21:35 +08:00
|
|
|
printLineState((*I)->Previous->State);
|
|
|
|
if ((*I)->NewLine) {
|
|
|
|
llvm::dbgs() << "Penalty for placing "
|
[clang-format] tweaked another case of lambda formatting
Summary:
This is done in order to improve cases where the lambda's body is moved too far to the right. Consider the following snippet with column limit set to 79:
```
void f() {
leader::MakeThisCallHere(&leader_service_,
cq_.get(),
[this, liveness](const leader::ReadRecordReq& req,
std::function<void()> done) {
logger_->HandleReadRecord(
req, resp, std::move(done));
});
leader::MakeAnother(&leader_service_,
cq_.get(),
[this, liveness](const leader::ReadRecordReq& req,
std::function<void()> done) {
logger_->HandleReadRecord(
req, resp, std::move(done), a);
});
}
```
The tool favors extra indentation for the lambda body and so the code incurs extra wrapping and adjacent calls are indented to a different level. I find this behavior annoying and I'd like the tool to favor new lines and, thus, use the extra width.
The fix, reduced, brings the following formatting.
Before:
function(1,
[] {
DoStuff();
//
},
1);
After:
function(
1,
[] {
DoStuff();
//
},
1);
Refer to the new tests in FormatTest.cpp
Contributed by oleg.smolsky!
Reviewers: djasper, klimek, krasimir
Subscribers: cfe-commits, owenpan
Tags: #clang
Differential Revision: https://reviews.llvm.org/D52676
llvm-svn: 345753
2018-11-01 01:56:57 +08:00
|
|
|
<< (*I)->Previous->State.NextToken->Tok.getName()
|
|
|
|
<< " on a new line: " << Penalty << "\n";
|
2015-05-11 16:21:35 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2015-01-24 03:37:25 +08:00
|
|
|
}
|
2015-05-11 16:21:35 +08:00
|
|
|
|
|
|
|
llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
|
|
|
|
};
|
2015-01-24 03:37:25 +08:00
|
|
|
|
2015-09-11 01:07:54 +08:00
|
|
|
} // anonymous namespace
|
2014-12-11 03:00:42 +08:00
|
|
|
|
|
|
|
unsigned
|
|
|
|
UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
|
|
|
|
bool DryRun, int AdditionalIndent,
|
2017-10-30 22:01:50 +08:00
|
|
|
bool FixBadIndentation,
|
|
|
|
unsigned FirstStartColumn,
|
|
|
|
unsigned NextStartColumn,
|
|
|
|
unsigned LastStartColumn) {
|
2015-05-12 17:23:57 +08:00
|
|
|
LineJoiner Joiner(Style, Keywords, Lines);
|
2014-12-11 03:00:42 +08:00
|
|
|
|
|
|
|
// Try to look up already computed penalty in DryRun-mode.
|
|
|
|
std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned> CacheKey(
|
|
|
|
&Lines, AdditionalIndent);
|
|
|
|
auto CacheIt = PenaltyCache.find(CacheKey);
|
|
|
|
if (DryRun && CacheIt != PenaltyCache.end())
|
|
|
|
return CacheIt->second;
|
|
|
|
|
|
|
|
assert(!Lines.empty());
|
|
|
|
unsigned Penalty = 0;
|
2015-05-12 17:23:57 +08:00
|
|
|
LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,
|
|
|
|
AdditionalIndent);
|
2014-12-11 03:00:42 +08:00
|
|
|
const AnnotatedLine *PreviousLine = nullptr;
|
2015-05-12 17:23:57 +08:00
|
|
|
const AnnotatedLine *NextLine = nullptr;
|
2015-11-01 08:27:35 +08:00
|
|
|
|
|
|
|
// The minimum level of consecutive lines that have been formatted.
|
|
|
|
unsigned RangeMinLevel = UINT_MAX;
|
|
|
|
|
2017-10-30 22:01:50 +08:00
|
|
|
bool FirstLine = true;
|
2015-05-12 17:23:57 +08:00
|
|
|
for (const AnnotatedLine *Line =
|
|
|
|
Joiner.getNextMergedLine(DryRun, IndentTracker);
|
2017-10-30 22:01:50 +08:00
|
|
|
Line; Line = NextLine, FirstLine = false) {
|
2015-05-12 17:23:57 +08:00
|
|
|
const AnnotatedLine &TheLine = *Line;
|
|
|
|
unsigned Indent = IndentTracker.getIndent();
|
2015-11-01 08:27:35 +08:00
|
|
|
|
|
|
|
// We continue formatting unchanged lines to adjust their indent, e.g. if a
|
|
|
|
// scope was added. However, we need to carefully stop doing this when we
|
|
|
|
// exit the scope of affected lines to prevent indenting a the entire
|
|
|
|
// remaining file if it currently missing a closing brace.
|
2018-04-23 17:34:26 +08:00
|
|
|
bool PreviousRBrace =
|
|
|
|
PreviousLine && PreviousLine->startsWith(tok::r_brace);
|
2015-11-01 08:27:35 +08:00
|
|
|
bool ContinueFormatting =
|
|
|
|
TheLine.Level > RangeMinLevel ||
|
2018-04-23 17:34:26 +08:00
|
|
|
(TheLine.Level == RangeMinLevel && !PreviousRBrace &&
|
|
|
|
!TheLine.startsWith(tok::r_brace));
|
2015-11-01 08:27:35 +08:00
|
|
|
|
|
|
|
bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
|
2015-10-28 09:08:22 +08:00
|
|
|
Indent != TheLine.First->OriginalColumn;
|
2015-05-07 20:26:30 +08:00
|
|
|
bool ShouldFormat = TheLine.Affected || FixIndentation;
|
2015-05-12 17:23:57 +08:00
|
|
|
// We cannot format this line; if the reason is that the line had a
|
|
|
|
// parsing error, remember that.
|
2017-04-21 22:35:20 +08:00
|
|
|
if (ShouldFormat && TheLine.Type == LT_Invalid && Status) {
|
|
|
|
Status->FormatComplete = false;
|
|
|
|
Status->Line =
|
|
|
|
SourceMgr.getSpellingLineNumber(TheLine.First->Tok.getLocation());
|
|
|
|
}
|
2014-12-11 03:00:42 +08:00
|
|
|
|
2015-05-12 17:23:57 +08:00
|
|
|
if (ShouldFormat && TheLine.Type != LT_Invalid) {
|
2017-10-30 22:01:50 +08:00
|
|
|
if (!DryRun) {
|
|
|
|
bool LastLine = Line->First->is(tok::eof);
|
2018-04-19 21:02:15 +08:00
|
|
|
formatFirstToken(TheLine, PreviousLine, Lines, Indent,
|
2017-10-30 22:01:50 +08:00
|
|
|
LastLine ? LastStartColumn : NextStartColumn + Indent);
|
|
|
|
}
|
2014-12-11 03:00:42 +08:00
|
|
|
|
2015-05-12 17:23:57 +08:00
|
|
|
NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
|
|
|
|
unsigned ColumnLimit = getColumnLimit(TheLine.InPPDirective, NextLine);
|
|
|
|
bool FitsIntoOneLine =
|
|
|
|
TheLine.Last->TotalLength + Indent <= ColumnLimit ||
|
2016-06-14 00:39:50 +08:00
|
|
|
(TheLine.Type == LT_ImportStatement &&
|
|
|
|
(Style.Language != FormatStyle::LK_JavaScript ||
|
|
|
|
!Style.JavaScriptWrapImports));
|
2015-05-12 17:23:57 +08:00
|
|
|
if (Style.ColumnLimit == 0)
|
2015-05-11 16:21:35 +08:00
|
|
|
NoColumnLimitLineFormatter(Indenter, Whitespaces, Style, this)
|
2017-10-30 22:01:50 +08:00
|
|
|
.formatLine(TheLine, NextStartColumn + Indent,
|
|
|
|
FirstLine ? FirstStartColumn : 0, DryRun);
|
2015-05-12 17:23:57 +08:00
|
|
|
else if (FitsIntoOneLine)
|
|
|
|
Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style, this)
|
2017-10-30 22:01:50 +08:00
|
|
|
.formatLine(TheLine, NextStartColumn + Indent,
|
|
|
|
FirstLine ? FirstStartColumn : 0, DryRun);
|
2015-05-12 17:23:57 +08:00
|
|
|
else
|
2015-05-11 16:21:35 +08:00
|
|
|
Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style, this)
|
2017-10-30 22:01:50 +08:00
|
|
|
.formatLine(TheLine, NextStartColumn + Indent,
|
|
|
|
FirstLine ? FirstStartColumn : 0, DryRun);
|
2015-11-01 08:27:35 +08:00
|
|
|
RangeMinLevel = std::min(RangeMinLevel, TheLine.Level);
|
2014-12-11 03:00:42 +08:00
|
|
|
} else {
|
2015-05-12 17:23:57 +08:00
|
|
|
// If no token in the current line is affected, we still need to format
|
|
|
|
// affected children.
|
|
|
|
if (TheLine.ChildrenAffected)
|
2016-02-29 20:26:20 +08:00
|
|
|
for (const FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next)
|
|
|
|
if (!Tok->Children.empty())
|
|
|
|
format(Tok->Children, DryRun);
|
2015-05-12 17:23:57 +08:00
|
|
|
|
|
|
|
// Adapt following lines on the current indent level to the same level
|
|
|
|
// unless the current \c AnnotatedLine is not at the beginning of a line.
|
|
|
|
bool StartsNewLine =
|
|
|
|
TheLine.First->NewlinesBefore > 0 || TheLine.First->IsFirst;
|
|
|
|
if (StartsNewLine)
|
|
|
|
IndentTracker.adjustToUnmodifiedLine(TheLine);
|
|
|
|
if (!DryRun) {
|
|
|
|
bool ReformatLeadingWhitespace =
|
|
|
|
StartsNewLine && ((PreviousLine && PreviousLine->Affected) ||
|
|
|
|
TheLine.LeadingEmptyLinesAffected);
|
|
|
|
// Format the first token.
|
|
|
|
if (ReformatLeadingWhitespace)
|
2018-04-19 21:02:15 +08:00
|
|
|
formatFirstToken(TheLine, PreviousLine, Lines,
|
2017-10-30 22:01:50 +08:00
|
|
|
TheLine.First->OriginalColumn,
|
2017-01-31 19:25:01 +08:00
|
|
|
TheLine.First->OriginalColumn);
|
2015-05-12 17:23:57 +08:00
|
|
|
else
|
|
|
|
Whitespaces->addUntouchableToken(*TheLine.First,
|
|
|
|
TheLine.InPPDirective);
|
|
|
|
|
|
|
|
// Notify the WhitespaceManager about the unchanged whitespace.
|
|
|
|
for (FormatToken *Tok = TheLine.First->Next; Tok; Tok = Tok->Next)
|
2014-12-11 03:00:42 +08:00
|
|
|
Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
|
|
|
|
}
|
2015-05-12 17:23:57 +08:00
|
|
|
NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
|
2015-11-01 08:27:35 +08:00
|
|
|
RangeMinLevel = UINT_MAX;
|
2014-12-11 03:00:42 +08:00
|
|
|
}
|
2015-01-24 03:37:25 +08:00
|
|
|
if (!DryRun)
|
|
|
|
markFinalized(TheLine.First);
|
2015-05-12 17:23:57 +08:00
|
|
|
PreviousLine = &TheLine;
|
2014-12-11 03:00:42 +08:00
|
|
|
}
|
|
|
|
PenaltyCache[CacheKey] = Penalty;
|
|
|
|
return Penalty;
|
|
|
|
}
|
|
|
|
|
2018-04-19 21:02:15 +08:00
|
|
|
void UnwrappedLineFormatter::formatFirstToken(
|
|
|
|
const AnnotatedLine &Line, const AnnotatedLine *PreviousLine,
|
|
|
|
const SmallVectorImpl<AnnotatedLine *> &Lines, unsigned Indent,
|
|
|
|
unsigned NewlineIndent) {
|
2017-09-20 17:51:03 +08:00
|
|
|
FormatToken &RootToken = *Line.First;
|
2015-05-12 17:23:57 +08:00
|
|
|
if (RootToken.is(tok::eof)) {
|
|
|
|
unsigned Newlines = std::min(RootToken.NewlinesBefore, 1u);
|
2017-10-30 22:01:50 +08:00
|
|
|
unsigned TokenIndent = Newlines ? NewlineIndent : 0;
|
|
|
|
Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent,
|
|
|
|
TokenIndent);
|
2015-05-12 17:23:57 +08:00
|
|
|
return;
|
|
|
|
}
|
2014-12-11 03:00:42 +08:00
|
|
|
unsigned Newlines =
|
|
|
|
std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
|
|
|
|
// Remove empty lines before "}" where applicable.
|
|
|
|
if (RootToken.is(tok::r_brace) &&
|
|
|
|
(!RootToken.Next ||
|
2018-04-19 21:02:15 +08:00
|
|
|
(RootToken.Next->is(tok::semi) && !RootToken.Next->Next)) &&
|
|
|
|
// Do not remove empty lines before namespace closing "}".
|
|
|
|
!getNamespaceToken(&Line, Lines))
|
2014-12-11 03:00:42 +08:00
|
|
|
Newlines = std::min(Newlines, 1u);
|
2017-11-18 02:06:33 +08:00
|
|
|
// Remove empty lines at the start of nested blocks (lambdas/arrow functions)
|
|
|
|
if (PreviousLine == nullptr && Line.Level > 0)
|
|
|
|
Newlines = std::min(Newlines, 1u);
|
2014-12-11 03:00:42 +08:00
|
|
|
if (Newlines == 0 && !RootToken.IsFirst)
|
|
|
|
Newlines = 1;
|
|
|
|
if (RootToken.IsFirst && !RootToken.HasUnescapedNewline)
|
|
|
|
Newlines = 0;
|
|
|
|
|
|
|
|
// Remove empty lines after "{".
|
|
|
|
if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine &&
|
|
|
|
PreviousLine->Last->is(tok::l_brace) &&
|
2018-09-05 15:44:02 +08:00
|
|
|
!PreviousLine->startsWithNamespace() &&
|
2014-12-11 03:00:42 +08:00
|
|
|
!startsExternCBlock(*PreviousLine))
|
|
|
|
Newlines = 1;
|
|
|
|
|
|
|
|
// Insert extra new line before access specifiers.
|
|
|
|
if (PreviousLine && PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) &&
|
|
|
|
RootToken.isAccessSpecifier() && RootToken.NewlinesBefore == 1)
|
|
|
|
++Newlines;
|
|
|
|
|
|
|
|
// Remove empty lines after access specifiers.
|
2015-03-09 16:13:55 +08:00
|
|
|
if (PreviousLine && PreviousLine->First->isAccessSpecifier() &&
|
|
|
|
(!PreviousLine->InPPDirective || !RootToken.HasUnescapedNewline))
|
2014-12-11 03:00:42 +08:00
|
|
|
Newlines = std::min(1u, Newlines);
|
|
|
|
|
2017-10-30 22:01:50 +08:00
|
|
|
if (Newlines)
|
|
|
|
Indent = NewlineIndent;
|
|
|
|
|
|
|
|
// Preprocessor directives get indented after the hash, if indented.
|
|
|
|
if (Line.Type == LT_PreprocessorDirective || Line.Type == LT_ImportStatement)
|
|
|
|
Indent = 0;
|
|
|
|
|
2017-01-31 19:25:01 +08:00
|
|
|
Whitespaces->replaceWhitespace(RootToken, Newlines, Indent, Indent,
|
|
|
|
Line.InPPDirective &&
|
|
|
|
!RootToken.HasUnescapedNewline);
|
2014-12-11 03:00:42 +08:00
|
|
|
}
|
|
|
|
|
2015-05-12 17:23:57 +08:00
|
|
|
unsigned
|
|
|
|
UnwrappedLineFormatter::getColumnLimit(bool InPPDirective,
|
|
|
|
const AnnotatedLine *NextLine) const {
|
|
|
|
// In preprocessor directives reserve two chars for trailing " \" if the
|
|
|
|
// next line continues the preprocessor directive.
|
|
|
|
bool ContinuesPPDirective =
|
2015-05-26 15:03:42 +08:00
|
|
|
InPPDirective &&
|
|
|
|
// If there is no next line, this is likely a child line and the parent
|
|
|
|
// continues the preprocessor directive.
|
|
|
|
(!NextLine ||
|
|
|
|
(NextLine->InPPDirective &&
|
|
|
|
// If there is an unescaped newline between this line and the next, the
|
|
|
|
// next line starts a new preprocessor directive.
|
|
|
|
!NextLine->First->HasUnescapedNewline));
|
2015-05-12 17:23:57 +08:00
|
|
|
return Style.ColumnLimit - (ContinuesPPDirective ? 2 : 0);
|
2014-12-11 03:00:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace format
|
|
|
|
} // namespace clang
|