forked from OSchip/llvm-project
[clang-format] Adds a formatter for aligning arrays of structs
This adds a new formatter to arrange array of struct initializers into neat columns. Differential Revision: https://reviews.llvm.org/D101868
This commit is contained in:
parent
5be3a1a064
commit
673c5ba584
|
@ -204,6 +204,41 @@ the configuration (without a prefix: ``Auto``).
|
|||
|
||||
|
||||
|
||||
**AlignArrayOfStructures** (``ArrayInitializerAlignmentStyle``)
|
||||
if not ``None``, when using initialization for an array of structs
|
||||
aligns the fields into columns.
|
||||
|
||||
Possible values:
|
||||
|
||||
* ``AIAS_Left`` (in configuration: ``Left``)
|
||||
Align array column and left justify the columns e.g.:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
struct test demo[] =
|
||||
{
|
||||
{56, 23, "hello"},
|
||||
{-1, 93463, "world"},
|
||||
{7, 5, "!!" }
|
||||
};
|
||||
|
||||
* ``AIAS_Right`` (in configuration: ``Right``)
|
||||
Align array column and right justify the columns e.g.:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
struct test demo[] =
|
||||
{
|
||||
{56, 23, "hello"},
|
||||
{-1, 93463, "world"},
|
||||
{ 7, 5, "!!"}
|
||||
};
|
||||
|
||||
* ``AIAS_None`` (in configuration: ``None``)
|
||||
Don't align array initializer columns.
|
||||
|
||||
|
||||
|
||||
**AlignConsecutiveAssignments** (``AlignConsecutiveStyle``)
|
||||
Style of aligning consecutive assignments.
|
||||
|
||||
|
|
|
@ -265,6 +265,9 @@ clang-format
|
|||
- Makes ``PointerAligment: Right`` working with ``AlignConsecutiveDeclarations``.
|
||||
(Fixes https://llvm.org/PR27353)
|
||||
|
||||
- Option ``AlignArrayOfStructure`` has been added to allow for ordering array-like
|
||||
initializers.
|
||||
|
||||
libclang
|
||||
--------
|
||||
|
||||
|
|
|
@ -90,6 +90,35 @@ struct FormatStyle {
|
|||
/// brackets.
|
||||
BracketAlignmentStyle AlignAfterOpenBracket;
|
||||
|
||||
/// Different style for aligning array initializers.
|
||||
enum ArrayInitializerAlignmentStyle {
|
||||
/// Align array column and left justify the columns e.g.:
|
||||
/// \code
|
||||
/// struct test demo[] =
|
||||
/// {
|
||||
/// {56, 23, "hello"},
|
||||
/// {-1, 93463, "world"},
|
||||
/// {7, 5, "!!" }
|
||||
/// };
|
||||
/// \endcode
|
||||
AIAS_Left,
|
||||
/// Align array column and right justify the columns e.g.:
|
||||
/// \code
|
||||
/// struct test demo[] =
|
||||
/// {
|
||||
/// {56, 23, "hello"},
|
||||
/// {-1, 93463, "world"},
|
||||
/// { 7, 5, "!!"}
|
||||
/// };
|
||||
/// \endcode
|
||||
AIAS_Right,
|
||||
/// Don't align array initializer columns.
|
||||
AIAS_None
|
||||
};
|
||||
/// if not ``None``, when using initialization for an array of structs
|
||||
/// aligns the fields into columns.
|
||||
ArrayInitializerAlignmentStyle AlignArrayOfStructures;
|
||||
|
||||
/// Styles for alignment of consecutive tokens. Tokens can be assignment signs
|
||||
/// (see
|
||||
/// ``AlignConsecutiveAssignments``), bitfield member separators (see
|
||||
|
@ -3272,6 +3301,7 @@ struct FormatStyle {
|
|||
bool operator==(const FormatStyle &R) const {
|
||||
return AccessModifierOffset == R.AccessModifierOffset &&
|
||||
AlignAfterOpenBracket == R.AlignAfterOpenBracket &&
|
||||
AlignArrayOfStructures == R.AlignArrayOfStructures &&
|
||||
AlignConsecutiveAssignments == R.AlignConsecutiveAssignments &&
|
||||
AlignConsecutiveBitFields == R.AlignConsecutiveBitFields &&
|
||||
AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations &&
|
||||
|
|
|
@ -143,6 +143,16 @@ template <> struct ScalarEnumerationTraits<FormatStyle::AlignConsecutiveStyle> {
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {
|
||||
static void enumeration(IO &IO,
|
||||
FormatStyle::ArrayInitializerAlignmentStyle &Value) {
|
||||
IO.enumCase(Value, "None", FormatStyle::AIAS_None);
|
||||
IO.enumCase(Value, "Left", FormatStyle::AIAS_Left);
|
||||
IO.enumCase(Value, "Right", FormatStyle::AIAS_Right);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
|
||||
static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
|
||||
IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
|
||||
|
@ -507,6 +517,7 @@ template <> struct MappingTraits<FormatStyle> {
|
|||
|
||||
IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
|
||||
IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
|
||||
IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);
|
||||
IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
|
||||
IO.mapOptional("AlignConsecutiveAssignments",
|
||||
Style.AlignConsecutiveAssignments);
|
||||
|
@ -943,6 +954,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
|
|||
LLVMStyle.AccessModifierOffset = -2;
|
||||
LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
|
||||
LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
|
||||
LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
|
||||
LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
|
||||
LLVMStyle.AlignTrailingComments = true;
|
||||
LLVMStyle.AlignConsecutiveAssignments = FormatStyle::ACS_None;
|
||||
|
|
|
@ -431,6 +431,15 @@ public:
|
|||
/// The next token in the unwrapped line.
|
||||
FormatToken *Next = nullptr;
|
||||
|
||||
/// The first token in set of column elements.
|
||||
bool StartsColumn = false;
|
||||
|
||||
/// This notes the start of the line of an array initializer.
|
||||
bool ArrayInitializerLineStart = false;
|
||||
|
||||
/// This starts an array initializer.
|
||||
bool IsArrayInitializer = false;
|
||||
|
||||
/// If this token starts a block, this contains all the unwrapped lines
|
||||
/// in it.
|
||||
SmallVector<AnnotatedLine *, 1> Children;
|
||||
|
|
|
@ -729,6 +729,21 @@ private:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool couldBeInStructArrayInitializer() const {
|
||||
if (Contexts.size() < 2)
|
||||
return false;
|
||||
// We want to back up no more then 2 context levels i.e.
|
||||
// . { { <-
|
||||
const auto End = std::next(Contexts.rbegin(), 2);
|
||||
auto Last = Contexts.rbegin();
|
||||
unsigned Depth = 0;
|
||||
for (; Last != End; ++Last) {
|
||||
if (Last->ContextKind == tok::l_brace)
|
||||
++Depth;
|
||||
}
|
||||
return Depth == 2 && Last->ContextKind != tok::l_brace;
|
||||
}
|
||||
|
||||
bool parseBrace() {
|
||||
if (CurrentToken) {
|
||||
FormatToken *Left = CurrentToken->Previous;
|
||||
|
@ -746,10 +761,17 @@ private:
|
|||
Left->Previous->is(TT_JsTypeColon))
|
||||
Contexts.back().IsExpression = false;
|
||||
|
||||
unsigned CommaCount = 0;
|
||||
while (CurrentToken) {
|
||||
if (CurrentToken->is(tok::r_brace)) {
|
||||
Left->MatchingParen = CurrentToken;
|
||||
CurrentToken->MatchingParen = Left;
|
||||
if (Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {
|
||||
if (Left->ParentBracket == tok::l_brace &&
|
||||
couldBeInStructArrayInitializer() && CommaCount > 0) {
|
||||
Contexts.back().InStructArrayInitializer = true;
|
||||
}
|
||||
}
|
||||
next();
|
||||
return true;
|
||||
}
|
||||
|
@ -773,9 +795,11 @@ private:
|
|||
Style.Language == FormatStyle::LK_JavaScript)
|
||||
Left->setType(TT_DictLiteral);
|
||||
}
|
||||
if (CurrentToken->is(tok::comma) &&
|
||||
Style.Language == FormatStyle::LK_JavaScript)
|
||||
Left->setType(TT_DictLiteral);
|
||||
if (CurrentToken->is(tok::comma)) {
|
||||
if (Style.Language == FormatStyle::LK_JavaScript)
|
||||
Left->setType(TT_DictLiteral);
|
||||
++CommaCount;
|
||||
}
|
||||
if (!consumeToken())
|
||||
return false;
|
||||
}
|
||||
|
@ -1339,6 +1363,12 @@ public:
|
|||
return LT_ObjCMethodDecl;
|
||||
}
|
||||
|
||||
for (const auto &ctx : Contexts) {
|
||||
if (ctx.InStructArrayInitializer) {
|
||||
return LT_ArrayOfStructInitializer;
|
||||
}
|
||||
}
|
||||
|
||||
return LT_Other;
|
||||
}
|
||||
|
||||
|
@ -1414,6 +1444,7 @@ private:
|
|||
bool IsForEachMacro = false;
|
||||
bool InCpp11AttributeSpecifier = false;
|
||||
bool InCSharpAttributeSpecifier = false;
|
||||
bool InStructArrayInitializer = false;
|
||||
};
|
||||
|
||||
/// Puts a new \c Context onto the stack \c Contexts for the lifetime
|
||||
|
@ -1429,7 +1460,16 @@ private:
|
|||
P.Contexts.back().IsExpression));
|
||||
}
|
||||
|
||||
~ScopedContextCreator() { P.Contexts.pop_back(); }
|
||||
~ScopedContextCreator() {
|
||||
if (P.Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {
|
||||
if (P.Contexts.back().InStructArrayInitializer) {
|
||||
P.Contexts.pop_back();
|
||||
P.Contexts.back().InStructArrayInitializer = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
P.Contexts.pop_back();
|
||||
}
|
||||
};
|
||||
|
||||
void modifyContext(const FormatToken &Current) {
|
||||
|
@ -2473,6 +2513,12 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
|
|||
: Line.FirstStartColumn + Line.First->ColumnWidth;
|
||||
FormatToken *Current = Line.First->Next;
|
||||
bool InFunctionDecl = Line.MightBeFunctionDecl;
|
||||
bool AlignArrayOfStructures =
|
||||
(Style.AlignArrayOfStructures != FormatStyle::AIAS_None &&
|
||||
Line.Type == LT_ArrayOfStructInitializer);
|
||||
if (AlignArrayOfStructures)
|
||||
calculateArrayInitializerColumnList(Line);
|
||||
|
||||
while (Current) {
|
||||
if (isFunctionDeclarationName(*Current, Line))
|
||||
Current->setType(TT_FunctionDeclarationName);
|
||||
|
@ -2592,6 +2638,45 @@ void TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {
|
|||
}
|
||||
}
|
||||
|
||||
void TokenAnnotator::calculateArrayInitializerColumnList(AnnotatedLine &Line) {
|
||||
if (Line.First == Line.Last) {
|
||||
return;
|
||||
}
|
||||
auto *CurrentToken = Line.First;
|
||||
CurrentToken->ArrayInitializerLineStart = true;
|
||||
unsigned Depth = 0;
|
||||
while (CurrentToken != nullptr && CurrentToken != Line.Last) {
|
||||
if (CurrentToken->is(tok::l_brace)) {
|
||||
CurrentToken->IsArrayInitializer = true;
|
||||
if (CurrentToken->Next != nullptr)
|
||||
CurrentToken->Next->MustBreakBefore = true;
|
||||
CurrentToken =
|
||||
calculateInitializerColumnList(Line, CurrentToken->Next, Depth + 1);
|
||||
} else {
|
||||
CurrentToken = CurrentToken->Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FormatToken *TokenAnnotator::calculateInitializerColumnList(
|
||||
AnnotatedLine &Line, FormatToken *CurrentToken, unsigned Depth) {
|
||||
while (CurrentToken != nullptr && CurrentToken != Line.Last) {
|
||||
if (CurrentToken->is(tok::l_brace))
|
||||
++Depth;
|
||||
else if (CurrentToken->is(tok::r_brace))
|
||||
--Depth;
|
||||
if (Depth == 2 && CurrentToken->isOneOf(tok::l_brace, tok::comma)) {
|
||||
CurrentToken = CurrentToken->Next;
|
||||
if (CurrentToken == nullptr)
|
||||
break;
|
||||
CurrentToken->StartsColumn = true;
|
||||
CurrentToken = CurrentToken->Previous;
|
||||
}
|
||||
CurrentToken = CurrentToken->Next;
|
||||
}
|
||||
return CurrentToken;
|
||||
}
|
||||
|
||||
unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
|
||||
const FormatToken &Tok,
|
||||
bool InFunctionDecl) {
|
||||
|
|
|
@ -31,7 +31,8 @@ enum LineType {
|
|||
LT_ObjCProperty, // An @property line.
|
||||
LT_Other,
|
||||
LT_PreprocessorDirective,
|
||||
LT_VirtualFunctionDecl
|
||||
LT_VirtualFunctionDecl,
|
||||
LT_ArrayOfStructInitializer,
|
||||
};
|
||||
|
||||
class AnnotatedLine {
|
||||
|
@ -189,6 +190,12 @@ private:
|
|||
|
||||
void calculateUnbreakableTailLengths(AnnotatedLine &Line);
|
||||
|
||||
void calculateArrayInitializerColumnList(AnnotatedLine &Line);
|
||||
|
||||
FormatToken *calculateInitializerColumnList(AnnotatedLine &Line,
|
||||
FormatToken *CurrentToken,
|
||||
unsigned Depth);
|
||||
|
||||
const FormatStyle &Style;
|
||||
|
||||
const AdditionalKeywords &Keywords;
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include "WhitespaceManager.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace clang {
|
||||
namespace format {
|
||||
|
@ -100,6 +102,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
|
|||
alignChainedConditionals();
|
||||
alignTrailingComments();
|
||||
alignEscapedNewlines();
|
||||
alignArrayInitializers();
|
||||
generateChanges();
|
||||
|
||||
return Replaces;
|
||||
|
@ -952,6 +955,305 @@ void WhitespaceManager::alignEscapedNewlines(unsigned Start, unsigned End,
|
|||
}
|
||||
}
|
||||
|
||||
void WhitespaceManager::alignArrayInitializers() {
|
||||
if (Style.AlignArrayOfStructures == FormatStyle::AIAS_None)
|
||||
return;
|
||||
|
||||
for (unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
|
||||
ChangeIndex < ChangeEnd; ++ChangeIndex) {
|
||||
auto &C = Changes[ChangeIndex];
|
||||
if (C.Tok->IsArrayInitializer) {
|
||||
bool FoundComplete = false;
|
||||
for (unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
|
||||
++InsideIndex) {
|
||||
if (Changes[InsideIndex].Tok == C.Tok->MatchingParen) {
|
||||
alignArrayInitializers(ChangeIndex, InsideIndex + 1);
|
||||
ChangeIndex = InsideIndex + 1;
|
||||
FoundComplete = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!FoundComplete)
|
||||
ChangeIndex = ChangeEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WhitespaceManager::alignArrayInitializers(unsigned Start, unsigned End) {
|
||||
|
||||
if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Right)
|
||||
alignArrayInitializersRightJustified(getCells(Start, End));
|
||||
else if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Left)
|
||||
alignArrayInitializersLeftJustified(getCells(Start, End));
|
||||
}
|
||||
|
||||
void WhitespaceManager::alignArrayInitializersRightJustified(
|
||||
CellDescriptions &&CellDescs) {
|
||||
auto &Cells = CellDescs.Cells;
|
||||
|
||||
// Now go through and fixup the spaces.
|
||||
auto *CellIter = Cells.begin();
|
||||
for (auto i = 0U; i < CellDescs.CellCount; i++, ++CellIter) {
|
||||
unsigned NetWidth = 0U;
|
||||
if (isSplitCell(*CellIter))
|
||||
NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
|
||||
auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
|
||||
|
||||
if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
|
||||
// So in here we want to see if there is a brace that falls
|
||||
// on a line that was split. If so on that line we make sure that
|
||||
// the spaces in front of the brace are enough.
|
||||
Changes[CellIter->Index].NewlinesBefore = 0;
|
||||
Changes[CellIter->Index].Spaces = 0;
|
||||
for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
|
||||
Next = Next->NextColumnElement) {
|
||||
Changes[Next->Index].Spaces = 0;
|
||||
Changes[Next->Index].NewlinesBefore = 0;
|
||||
}
|
||||
// Unless the array is empty, we need the position of all the
|
||||
// immediately adjacent cells
|
||||
if (CellIter != Cells.begin()) {
|
||||
auto ThisNetWidth =
|
||||
getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
|
||||
auto MaxNetWidth =
|
||||
getMaximumNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces,
|
||||
CellDescs.CellCount);
|
||||
if (ThisNetWidth < MaxNetWidth)
|
||||
Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
|
||||
auto RowCount = 1U;
|
||||
auto Offset = std::distance(Cells.begin(), CellIter);
|
||||
for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
|
||||
Next = Next->NextColumnElement) {
|
||||
auto *Start = (Cells.begin() + RowCount * CellDescs.CellCount);
|
||||
auto *End = Start + Offset;
|
||||
ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
|
||||
if (ThisNetWidth < MaxNetWidth)
|
||||
Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
|
||||
++RowCount;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto ThisWidth =
|
||||
calculateCellWidth(CellIter->Index, CellIter->EndIndex, true) +
|
||||
NetWidth;
|
||||
if (Changes[CellIter->Index].NewlinesBefore == 0) {
|
||||
Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
|
||||
Changes[CellIter->Index].Spaces += (i > 0) ? 1 : 0;
|
||||
}
|
||||
alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
|
||||
for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
|
||||
Next = Next->NextColumnElement) {
|
||||
ThisWidth =
|
||||
calculateCellWidth(Next->Index, Next->EndIndex, true) + NetWidth;
|
||||
if (Changes[Next->Index].NewlinesBefore == 0) {
|
||||
Changes[Next->Index].Spaces = (CellWidth - ThisWidth);
|
||||
Changes[Next->Index].Spaces += (i > 0) ? 1 : 0;
|
||||
}
|
||||
alignToStartOfCell(Next->Index, Next->EndIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WhitespaceManager::alignArrayInitializersLeftJustified(
|
||||
CellDescriptions &&CellDescs) {
|
||||
auto &Cells = CellDescs.Cells;
|
||||
|
||||
// Now go through and fixup the spaces.
|
||||
auto *CellIter = Cells.begin();
|
||||
// The first cell needs to be against the left brace.
|
||||
if (Changes[CellIter->Index].NewlinesBefore == 0)
|
||||
Changes[CellIter->Index].Spaces = 0;
|
||||
else
|
||||
Changes[CellIter->Index].Spaces = CellDescs.InitialSpaces;
|
||||
++CellIter;
|
||||
for (auto i = 1U; i < CellDescs.CellCount; i++, ++CellIter) {
|
||||
unsigned NetWidth = 0U;
|
||||
if (isSplitCell(*CellIter))
|
||||
NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
|
||||
auto MaxNetWidth = getMaximumNetWidth(
|
||||
Cells.begin(), CellIter, CellDescs.InitialSpaces, CellDescs.CellCount);
|
||||
auto ThisNetWidth =
|
||||
getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
|
||||
if (Changes[CellIter->Index].NewlinesBefore == 0) {
|
||||
Changes[CellIter->Index].Spaces =
|
||||
MaxNetWidth - ThisNetWidth +
|
||||
(Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1 : 0);
|
||||
}
|
||||
auto RowCount = 1U;
|
||||
auto Offset = std::distance(Cells.begin(), CellIter);
|
||||
for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
|
||||
Next = Next->NextColumnElement) {
|
||||
auto *Start = (Cells.begin() + RowCount * CellDescs.CellCount);
|
||||
auto *End = Start + Offset;
|
||||
auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
|
||||
if (Changes[Next->Index].NewlinesBefore == 0) {
|
||||
Changes[Next->Index].Spaces =
|
||||
MaxNetWidth - ThisNetWidth +
|
||||
(Changes[Next->Index].Tok->isNot(tok::r_brace) ? 1 : 0);
|
||||
}
|
||||
++RowCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WhitespaceManager::isSplitCell(const CellDescription &Cell) {
|
||||
if (Cell.HasSplit)
|
||||
return true;
|
||||
for (const auto *Next = Cell.NextColumnElement; Next != nullptr;
|
||||
Next = Next->NextColumnElement) {
|
||||
if (Next->HasSplit)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start,
|
||||
unsigned End) {
|
||||
|
||||
unsigned Depth = 0;
|
||||
unsigned Cell = 0;
|
||||
unsigned CellCount = 0;
|
||||
unsigned InitialSpaces = 0;
|
||||
unsigned InitialTokenLength = 0;
|
||||
unsigned EndSpaces = 0;
|
||||
SmallVector<CellDescription> Cells;
|
||||
const FormatToken *MatchingParen = nullptr;
|
||||
for (unsigned i = Start; i < End; ++i) {
|
||||
auto &C = Changes[i];
|
||||
if (C.Tok->is(tok::l_brace))
|
||||
++Depth;
|
||||
else if (C.Tok->is(tok::r_brace))
|
||||
--Depth;
|
||||
if (Depth == 2) {
|
||||
if (C.Tok->is(tok::l_brace)) {
|
||||
Cell = 0;
|
||||
MatchingParen = C.Tok->MatchingParen;
|
||||
if (InitialSpaces == 0) {
|
||||
InitialSpaces = C.Spaces + C.TokenLength;
|
||||
InitialTokenLength = C.TokenLength;
|
||||
auto j = i - 1;
|
||||
for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
|
||||
InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
|
||||
InitialTokenLength += Changes[j].TokenLength;
|
||||
}
|
||||
if (C.NewlinesBefore == 0) {
|
||||
InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
|
||||
InitialTokenLength += Changes[j].TokenLength;
|
||||
}
|
||||
}
|
||||
} else if (C.Tok->is(tok::comma)) {
|
||||
if (!Cells.empty())
|
||||
Cells.back().EndIndex = i;
|
||||
Cell++;
|
||||
}
|
||||
} else if (Depth == 1) {
|
||||
if (C.Tok == MatchingParen) {
|
||||
if (!Cells.empty())
|
||||
Cells.back().EndIndex = i;
|
||||
Cells.push_back(CellDescription{i, ++Cell, i + 1, false, nullptr});
|
||||
CellCount = Cell + 1;
|
||||
// Go to the next non-comment and ensure there is a break in front
|
||||
const auto *NextNonComment = C.Tok->getNextNonComment();
|
||||
while (NextNonComment->is(tok::comma))
|
||||
NextNonComment = NextNonComment->getNextNonComment();
|
||||
auto j = i;
|
||||
while (Changes[j].Tok != NextNonComment && j < End)
|
||||
j++;
|
||||
if (j < End && Changes[j].NewlinesBefore == 0 &&
|
||||
Changes[j].Tok->isNot(tok::r_brace)) {
|
||||
Changes[j].NewlinesBefore = 1;
|
||||
// Account for the added token lengths
|
||||
Changes[j].Spaces = InitialSpaces - InitialTokenLength;
|
||||
}
|
||||
} else if (C.Tok->is(tok::comment)) {
|
||||
// Trailing comments stay at a space past the last token
|
||||
C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 1 : 2;
|
||||
} else if (C.Tok->is(tok::l_brace)) {
|
||||
// We need to make sure that the ending braces is aligned to the
|
||||
// start of our initializer
|
||||
auto j = i - 1;
|
||||
for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
|
||||
; // Nothing the loop does the work
|
||||
EndSpaces = Changes[j].Spaces;
|
||||
}
|
||||
} else if (Depth == 0 && C.Tok->is(tok::r_brace)) {
|
||||
C.NewlinesBefore = 1;
|
||||
C.Spaces = EndSpaces;
|
||||
}
|
||||
if (C.Tok->StartsColumn) {
|
||||
// This gets us past tokens that have been split over multiple
|
||||
// lines
|
||||
bool HasSplit = false;
|
||||
if (Changes[i].NewlinesBefore > 0) {
|
||||
// So if we split a line previously and the tail line + this token is
|
||||
// less then the column limit we remove the split here and just put
|
||||
// the column start at a space past the comma
|
||||
auto j = i - 1;
|
||||
if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) &&
|
||||
Changes[j - 1].NewlinesBefore > 0) {
|
||||
--j;
|
||||
auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
|
||||
if (LineLimit < Style.ColumnLimit) {
|
||||
Changes[i].NewlinesBefore = 0;
|
||||
Changes[i].Spaces = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (Changes[i].NewlinesBefore > 0 && Changes[i].Tok == C.Tok) {
|
||||
Changes[i].Spaces = InitialSpaces;
|
||||
++i;
|
||||
HasSplit = true;
|
||||
}
|
||||
if (Changes[i].Tok != C.Tok)
|
||||
--i;
|
||||
Cells.push_back(CellDescription{i, Cell, i, HasSplit, nullptr});
|
||||
}
|
||||
}
|
||||
|
||||
return linkCells({Cells, CellCount, InitialSpaces});
|
||||
}
|
||||
|
||||
unsigned WhitespaceManager::calculateCellWidth(unsigned Start, unsigned End,
|
||||
bool WithSpaces) const {
|
||||
unsigned CellWidth = 0;
|
||||
for (auto i = Start; i < End; i++) {
|
||||
if (Changes[i].NewlinesBefore > 0)
|
||||
CellWidth = 0;
|
||||
CellWidth += Changes[i].TokenLength;
|
||||
CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
|
||||
}
|
||||
return CellWidth;
|
||||
}
|
||||
|
||||
void WhitespaceManager::alignToStartOfCell(unsigned Start, unsigned End) {
|
||||
if ((End - Start) <= 1)
|
||||
return;
|
||||
// If the line is broken anywhere in there make sure everything
|
||||
// is aligned to the parent
|
||||
for (auto i = Start + 1; i < End; i++) {
|
||||
if (Changes[i].NewlinesBefore > 0)
|
||||
Changes[i].Spaces = Changes[Start].Spaces;
|
||||
}
|
||||
}
|
||||
|
||||
WhitespaceManager::CellDescriptions
|
||||
WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
|
||||
auto &Cells = CellDesc.Cells;
|
||||
for (auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
|
||||
if (CellIter->NextColumnElement == nullptr &&
|
||||
((CellIter + 1) != Cells.end())) {
|
||||
for (auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
|
||||
if (NextIter->Cell == CellIter->Cell) {
|
||||
CellIter->NextColumnElement = &(*NextIter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::move(CellDesc);
|
||||
}
|
||||
|
||||
void WhitespaceManager::generateChanges() {
|
||||
for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
|
||||
const Change &C = Changes[i];
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "TokenAnnotator.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Format/Format.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
|
@ -173,6 +175,28 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
struct CellDescription {
|
||||
unsigned Index = 0;
|
||||
unsigned Cell = 0;
|
||||
unsigned EndIndex = 0;
|
||||
bool HasSplit = false;
|
||||
CellDescription *NextColumnElement = nullptr;
|
||||
|
||||
constexpr bool operator==(const CellDescription &Other) const {
|
||||
return Index == Other.Index && Cell == Other.Cell &&
|
||||
EndIndex == Other.EndIndex;
|
||||
}
|
||||
constexpr bool operator!=(const CellDescription &Other) const {
|
||||
return !(*this == Other);
|
||||
}
|
||||
};
|
||||
|
||||
struct CellDescriptions {
|
||||
SmallVector<CellDescription> Cells;
|
||||
unsigned CellCount = 0;
|
||||
unsigned InitialSpaces = 0;
|
||||
};
|
||||
|
||||
/// Calculate \c IsTrailingComment, \c TokenLength for the last tokens
|
||||
/// or token parts in a line and \c PreviousEndOfTokenColumn and
|
||||
/// \c EscapedNewlineColumn for the first tokens or token parts in a line.
|
||||
|
@ -207,6 +231,89 @@ private:
|
|||
/// the specified \p Column.
|
||||
void alignEscapedNewlines(unsigned Start, unsigned End, unsigned Column);
|
||||
|
||||
/// Align Array Initializers over all \c Changes.
|
||||
void alignArrayInitializers();
|
||||
|
||||
/// Align Array Initializers from change \p Start to change \p End at
|
||||
/// the specified \p Column.
|
||||
void alignArrayInitializers(unsigned Start, unsigned End);
|
||||
|
||||
/// Align Array Initializers being careful to right justify the columns
|
||||
/// as described by \p CellDescs.
|
||||
void alignArrayInitializersRightJustified(CellDescriptions &&CellDescs);
|
||||
|
||||
/// Align Array Initializers being careful to leftt justify the columns
|
||||
/// as described by \p CellDescs.
|
||||
void alignArrayInitializersLeftJustified(CellDescriptions &&CellDescs);
|
||||
|
||||
/// Calculate the cell width between two indexes.
|
||||
unsigned calculateCellWidth(unsigned Start, unsigned End,
|
||||
bool WithSpaces = false) const;
|
||||
|
||||
/// Get a set of fully specified CellDescriptions between \p Start and
|
||||
/// \p End of the change list.
|
||||
CellDescriptions getCells(unsigned Start, unsigned End);
|
||||
|
||||
/// Does this \p Cell contain a split element?
|
||||
static bool isSplitCell(const CellDescription &Cell);
|
||||
|
||||
/// Get the width of the preceeding cells from \p Start to \p End.
|
||||
template <typename I>
|
||||
auto getNetWidth(const I &Start, const I &End, unsigned InitialSpaces) const {
|
||||
auto NetWidth = InitialSpaces;
|
||||
for (auto PrevIter = Start; PrevIter != End; ++PrevIter) {
|
||||
// If we broke the line the initial spaces are already
|
||||
// accounted for.
|
||||
if (Changes[PrevIter->Index].NewlinesBefore > 0)
|
||||
NetWidth = 0;
|
||||
NetWidth +=
|
||||
calculateCellWidth(PrevIter->Index, PrevIter->EndIndex, true) + 1;
|
||||
}
|
||||
return NetWidth;
|
||||
}
|
||||
|
||||
/// Get the maximum width of a cell in a sequence of columns.
|
||||
template <typename I>
|
||||
unsigned getMaximumCellWidth(I CellIter, unsigned NetWidth) const {
|
||||
unsigned CellWidth =
|
||||
calculateCellWidth(CellIter->Index, CellIter->EndIndex, true);
|
||||
if (Changes[CellIter->Index].NewlinesBefore == 0)
|
||||
CellWidth += NetWidth;
|
||||
for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
|
||||
Next = Next->NextColumnElement) {
|
||||
auto ThisWidth = calculateCellWidth(Next->Index, Next->EndIndex, true);
|
||||
if (Changes[Next->Index].NewlinesBefore == 0)
|
||||
ThisWidth += NetWidth;
|
||||
CellWidth = std::max(CellWidth, ThisWidth);
|
||||
}
|
||||
return CellWidth;
|
||||
}
|
||||
|
||||
/// Get The maximum width of all columns to a given cell.
|
||||
template <typename I>
|
||||
unsigned getMaximumNetWidth(const I &CellStart, const I &CellStop,
|
||||
unsigned InitialSpaces,
|
||||
unsigned CellCount) const {
|
||||
auto MaxNetWidth = getNetWidth(CellStart, CellStop, InitialSpaces);
|
||||
auto RowCount = 1U;
|
||||
auto Offset = std::distance(CellStart, CellStop);
|
||||
for (const auto *Next = CellStop->NextColumnElement; Next != nullptr;
|
||||
Next = Next->NextColumnElement) {
|
||||
auto Start = (CellStart + RowCount * CellCount);
|
||||
auto End = Start + Offset;
|
||||
MaxNetWidth =
|
||||
std::max(MaxNetWidth, getNetWidth(Start, End, InitialSpaces));
|
||||
++RowCount;
|
||||
}
|
||||
return MaxNetWidth;
|
||||
}
|
||||
|
||||
/// Align a split cell with a newline to the first element in the cell.
|
||||
void alignToStartOfCell(unsigned Start, unsigned End);
|
||||
|
||||
/// Link the Cell pointers in the list of Cells.
|
||||
static CellDescriptions linkCells(CellDescriptions &&CellDesc);
|
||||
|
||||
/// Fill \c Replaces with the replacements for all effective changes.
|
||||
void generateChanges();
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
// RUN: grep -Ev "// *[A-Z-]+:" %s \
|
||||
// RUN: | clang-format -style="{BasedOnStyle: LLVM, AlignArrayOfStructures: Right}" %s \
|
||||
// RUN: | FileCheck -strict-whitespace -check-prefix=CHECK1 %s
|
||||
// RUN: grep -Ev "// *[A-Z-]+:" %s \
|
||||
// RUN: | clang-format -style="{BasedOnStyle: LLVM, AlignArrayOfStructures: Left}" %s \
|
||||
// RUN: | FileCheck -strict-whitespace -check-prefix=CHECK2 %s
|
||||
struct test {
|
||||
int a;
|
||||
int b;
|
||||
const char *c;
|
||||
};
|
||||
|
||||
struct toast {
|
||||
int a;
|
||||
const char *b;
|
||||
int c;
|
||||
float d;
|
||||
};
|
||||
|
||||
void f() {
|
||||
struct test demo[] = {{56, 23, "hello"}, {-1, 93463, "world"}, {7, 5, "!!"}};
|
||||
// CHECK1: {{^[[:space:]]{2}struct test demo\[\] = \{$}}
|
||||
// CHECK1-NEXT: {{([[:space:]]{4})}}{56, 23, "hello"},
|
||||
// CHECK1-NEXT: {{([[:space:]]{4})}}{-1, 93463, "world"},
|
||||
// CHECK1-NEXT: {{([[:space:]]{4})}}{ 7, 5, "!!"}
|
||||
// CHECK1-NEXT: {{^[[:space:]]{2}\};$}}
|
||||
}
|
||||
|
||||
void g() {
|
||||
struct toast demo[] = {
|
||||
{56, "hello world I have some things to say", 30, 4.2},
|
||||
{93463, "those things are really comments", 1, 3.1},
|
||||
{7, "about a wide range of topics", 789, .112233}};
|
||||
// CHECK1: {{^[[:space:]]{2}struct toast demo\[\] = \{$}}
|
||||
// CHECK1-NEXT: {{([[:space:]]{4})}}{ 56, "hello world I have some things to say", 30, 4.2},
|
||||
// CHECK1-NEXT: {{([[:space:]]{4})}}{93463, "those things are really comments", 1, 3.1},
|
||||
// CHECK1-NEXT: {{([[:space:]]{4})}}{ 7, "about a wide range of topics", 789, .112233}
|
||||
// CHECK1-NEXT: {{^[[:space:]]{2}\};$}}
|
||||
}
|
||||
|
||||
void h() {
|
||||
struct test demo[] = {{56, 23, "hello"}, {-1, 93463, "world"}, {7, 5, "!!"}};
|
||||
// CHECK2: {{^[[:space:]]{2}struct test demo\[\] = \{$}}
|
||||
// CHECK2-NEXT: {{([[:space:]]{4})}}{56, 23, "hello"},
|
||||
// CHECK2-NEXT: {{([[:space:]]{4})}}{-1, 93463, "world"},
|
||||
// CHECK2-NEXT: {{([[:space:]]{4})}}{7, 5, "!!" }
|
||||
// CHECK2-NEXT: {{^[[:space:]]{2}\};$}}
|
||||
}
|
||||
|
||||
void i() {
|
||||
struct toast demo[] = {
|
||||
{56, "hello world I have some things to say", 30, 4.2},
|
||||
{93463, "those things are really comments", 1, 3.1},
|
||||
{7, "about a wide range of topics", 789, .112233}};
|
||||
// CHECK2: {{^[[:space:]]{2}struct toast demo\[\] = \{$}}
|
||||
// CHECK2-NEXT: {{([[:space:]]{4})}}{56, "hello world I have some things to say", 30, 4.2 },
|
||||
// CHECK2-NEXT: {{([[:space:]]{4})}}{93463, "those things are really comments", 1, 3.1 },
|
||||
// CHECK2-NEXT: {{([[:space:]]{4})}}{7, "about a wide range of topics", 789, .112233}
|
||||
// CHECK2-NEXT: {{^[[:space:]]{2}\};$}}
|
||||
}
|
|
@ -16602,6 +16602,407 @@ TEST_F(FormatTest, CatchExceptionReferenceBinding) {
|
|||
getLLVMStyle());
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, CatchAlignArrayOfStructuresRightAlignment) {
|
||||
auto Style = getLLVMStyle();
|
||||
Style.AlignArrayOfStructures = FormatStyle::AIAS_Right;
|
||||
Style.AlignConsecutiveAssignments =
|
||||
FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
|
||||
Style.AlignConsecutiveDeclarations =
|
||||
FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
|
||||
verifyFormat("struct test demo[] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" { 7, 5, \"!!\"}\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("struct test demo[] = {\n"
|
||||
" {56, 23, \"hello\"}, // first line\n"
|
||||
" {-1, 93463, \"world\"}, // second line\n"
|
||||
" { 7, 5, \"!!\"} // third line\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("struct test demo[4] = {\n"
|
||||
" { 56, 23, 21, \"oh\"}, // first line\n"
|
||||
" { -1, 93463, 22, \"my\"}, // second line\n"
|
||||
" { 7, 5, 1, \"goodness\"} // third line\n"
|
||||
" {234, 5, 1, \"gracious\"} // fourth line\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("struct test demo[3] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" { 7, 5, \"!!\"}\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("struct test demo[3] = {\n"
|
||||
" {int{56}, 23, \"hello\"},\n"
|
||||
" {int{-1}, 93463, \"world\"},\n"
|
||||
" { int{7}, 5, \"!!\"}\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("struct test demo[] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" { 7, 5, \"!!\"},\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("test demo[] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" { 7, 5, \"!!\"},\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("demo = std::array<struct test, 3>{\n"
|
||||
" test{56, 23, \"hello\"},\n"
|
||||
" test{-1, 93463, \"world\"},\n"
|
||||
" test{ 7, 5, \"!!\"},\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("test demo[] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
"#if X\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
"#endif\n"
|
||||
" { 7, 5, \"!!\"}\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat(
|
||||
"test demo[] = {\n"
|
||||
" { 7, 23,\n"
|
||||
" \"hello world i am a very long line that really, in any\"\n"
|
||||
" \"just world, ought to be split over multiple lines\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" {56, 5, \"!!\"}\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("return GradForUnaryCwise(g, {\n"
|
||||
" {{\"sign\"}, \"Sign\", "
|
||||
" {\"x\", \"dy\"}},\n"
|
||||
" { {\"dx\"}, \"Mul\", {\"dy\""
|
||||
", \"sign\"}},\n"
|
||||
"});\n",
|
||||
Style);
|
||||
|
||||
Style.ColumnLimit = 0;
|
||||
EXPECT_EQ(
|
||||
"test demo[] = {\n"
|
||||
" {56, 23, \"hello world i am a very long line that really, "
|
||||
"in any just world, ought to be split over multiple lines\"},\n"
|
||||
" {-1, 93463, "
|
||||
" \"world\"},\n"
|
||||
" { 7, 5, "
|
||||
" \"!!\"},\n"
|
||||
"};",
|
||||
format("test demo[] = {{56, 23, \"hello world i am a very long line "
|
||||
"that really, in any just world, ought to be split over multiple "
|
||||
"lines\"},{-1, 93463, \"world\"},{7, 5, \"!!\"},};",
|
||||
Style));
|
||||
|
||||
Style.ColumnLimit = 80;
|
||||
verifyFormat("test demo[] = {\n"
|
||||
" {56, 23, /* a comment */ \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" { 7, 5, \"!!\"}\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("test demo[] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\" /* comment here */},\n"
|
||||
" { 7, 5, \"!!\"}\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("test demo[] = {\n"
|
||||
" {56, /* a comment */ 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" { 7, 5, \"!!\"}\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
Style.ColumnLimit = 20;
|
||||
EXPECT_EQ(
|
||||
"demo = std::array<\n"
|
||||
" struct test, 3>{\n"
|
||||
" test{\n"
|
||||
" 56, 23,\n"
|
||||
" \"hello \"\n"
|
||||
" \"world i \"\n"
|
||||
" \"am a very \"\n"
|
||||
" \"long line \"\n"
|
||||
" \"that \"\n"
|
||||
" \"really, \"\n"
|
||||
" \"in any \"\n"
|
||||
" \"just \"\n"
|
||||
" \"world, \"\n"
|
||||
" \"ought to \"\n"
|
||||
" \"be split \"\n"
|
||||
" \"over \"\n"
|
||||
" \"multiple \"\n"
|
||||
" \"lines\"},\n"
|
||||
" test{-1, 93463,\n"
|
||||
" \"world\"},\n"
|
||||
" test{ 7, 5,\n"
|
||||
" \"!!\" },\n"
|
||||
"};",
|
||||
format("demo = std::array<struct test, 3>{test{56, 23, \"hello world "
|
||||
"i am a very long line that really, in any just world, ought "
|
||||
"to be split over multiple lines\"},test{-1, 93463, \"world\"},"
|
||||
"test{7, 5, \"!!\"},};",
|
||||
Style));
|
||||
// This caused a core dump by enabling Alignment in the LLVMStyle globally
|
||||
Style = getLLVMStyleWithColumns(50);
|
||||
Style.AlignArrayOfStructures = FormatStyle::AIAS_Right;
|
||||
verifyFormat("static A x = {\n"
|
||||
" {{init1, init2, init3, init4},\n"
|
||||
" {init1, init2, init3, init4}}\n"
|
||||
"};",
|
||||
Style);
|
||||
Style.ColumnLimit = 100;
|
||||
EXPECT_EQ(
|
||||
"test demo[] = {\n"
|
||||
" {56, 23,\n"
|
||||
" \"hello world i am a very long line that really, in any just world"
|
||||
", ought to be split over \"\n"
|
||||
" \"multiple lines\" },\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" { 7, 5, \"!!\"},\n"
|
||||
"};",
|
||||
format("test demo[] = {{56, 23, \"hello world i am a very long line "
|
||||
"that really, in any just world, ought to be split over multiple "
|
||||
"lines\"},{-1, 93463, \"world\"},{7, 5, \"!!\"},};",
|
||||
Style));
|
||||
|
||||
Style = getLLVMStyleWithColumns(50);
|
||||
Style.AlignArrayOfStructures = FormatStyle::AIAS_Right;
|
||||
Style.AlignConsecutiveAssignments =
|
||||
FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
|
||||
Style.AlignConsecutiveDeclarations =
|
||||
FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
|
||||
verifyFormat("struct test demo[] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" { 7, 5, \"!!\"}\n"
|
||||
"};\n"
|
||||
"static A x = {\n"
|
||||
" {{init1, init2, init3, init4},\n"
|
||||
" {init1, init2, init3, init4}}\n"
|
||||
"};",
|
||||
Style);
|
||||
Style.ColumnLimit = 100;
|
||||
Style.AlignConsecutiveAssignments =
|
||||
FormatStyle::AlignConsecutiveStyle::ACS_AcrossComments;
|
||||
Style.AlignConsecutiveDeclarations =
|
||||
FormatStyle::AlignConsecutiveStyle::ACS_AcrossComments;
|
||||
verifyFormat("struct test demo[] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" { 7, 5, \"!!\"}\n"
|
||||
"};\n"
|
||||
"struct test demo[4] = {\n"
|
||||
" { 56, 23, 21, \"oh\"}, // first line\n"
|
||||
" { -1, 93463, 22, \"my\"}, // second line\n"
|
||||
" { 7, 5, 1, \"goodness\"} // third line\n"
|
||||
" {234, 5, 1, \"gracious\"} // fourth line\n"
|
||||
"};\n",
|
||||
Style);
|
||||
EXPECT_EQ(
|
||||
"test demo[] = {\n"
|
||||
" {56,\n"
|
||||
" \"hello world i am a very long line that really, in any just world"
|
||||
", ought to be split over \"\n"
|
||||
" \"multiple lines\", 23},\n"
|
||||
" {-1, \"world\", 93463},\n"
|
||||
" { 7, \"!!\", 5},\n"
|
||||
"};",
|
||||
format("test demo[] = {{56, \"hello world i am a very long line "
|
||||
"that really, in any just world, ought to be split over multiple "
|
||||
"lines\", 23},{-1, \"world\", 93463},{7, \"!!\", 5},};",
|
||||
Style));
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, CatchAlignArrayOfStructuresLeftAlignment) {
|
||||
auto Style = getLLVMStyle();
|
||||
Style.AlignArrayOfStructures = FormatStyle::AIAS_Left;
|
||||
verifyFormat("struct test demo[] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" {7, 5, \"!!\" }\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("struct test demo[] = {\n"
|
||||
" {56, 23, \"hello\"}, // first line\n"
|
||||
" {-1, 93463, \"world\"}, // second line\n"
|
||||
" {7, 5, \"!!\" } // third line\n"
|
||||
"};\n",
|
||||
Style);
|
||||
verifyFormat("struct test demo[4] = {\n"
|
||||
" {56, 23, 21, \"oh\" }, // first line\n"
|
||||
" {-1, 93463, 22, \"my\" }, // second line\n"
|
||||
" {7, 5, 1, \"goodness\"} // third line\n"
|
||||
" {234, 5, 1, \"gracious\"} // fourth line\n"
|
||||
"};\n",
|
||||
Style);
|
||||
verifyFormat("struct test demo[3] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" {7, 5, \"!!\" }\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("struct test demo[3] = {\n"
|
||||
" {int{56}, 23, \"hello\"},\n"
|
||||
" {int{-1}, 93463, \"world\"},\n"
|
||||
" {int{7}, 5, \"!!\" }\n"
|
||||
"};\n",
|
||||
Style);
|
||||
verifyFormat("struct test demo[] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" {7, 5, \"!!\" },\n"
|
||||
"};\n",
|
||||
Style);
|
||||
verifyFormat("test demo[] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" {7, 5, \"!!\" },\n"
|
||||
"};\n",
|
||||
Style);
|
||||
verifyFormat("demo = std::array<struct test, 3>{\n"
|
||||
" test{56, 23, \"hello\"},\n"
|
||||
" test{-1, 93463, \"world\"},\n"
|
||||
" test{7, 5, \"!!\" },\n"
|
||||
"};\n",
|
||||
Style);
|
||||
verifyFormat("test demo[] = {\n"
|
||||
" {56, 23, \"hello\"},\n"
|
||||
"#if X\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
"#endif\n"
|
||||
" {7, 5, \"!!\" }\n"
|
||||
"};\n",
|
||||
Style);
|
||||
verifyFormat(
|
||||
"test demo[] = {\n"
|
||||
" {7, 23,\n"
|
||||
" \"hello world i am a very long line that really, in any\"\n"
|
||||
" \"just world, ought to be split over multiple lines\"},\n"
|
||||
" {-1, 93463, \"world\" },\n"
|
||||
" {56, 5, \"!!\" }\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("return GradForUnaryCwise(g, {\n"
|
||||
" {{\"sign\"}, \"Sign\", {\"x\", "
|
||||
"\"dy\"} },\n"
|
||||
" {{\"dx\"}, \"Mul\", "
|
||||
"{\"dy\", \"sign\"}},\n"
|
||||
"});\n",
|
||||
Style);
|
||||
|
||||
Style.ColumnLimit = 0;
|
||||
EXPECT_EQ(
|
||||
"test demo[] = {\n"
|
||||
" {56, 23, \"hello world i am a very long line that really, in any "
|
||||
"just world, ought to be split over multiple lines\"},\n"
|
||||
" {-1, 93463, \"world\" "
|
||||
" },\n"
|
||||
" {7, 5, \"!!\" "
|
||||
" },\n"
|
||||
"};",
|
||||
format("test demo[] = {{56, 23, \"hello world i am a very long line "
|
||||
"that really, in any just world, ought to be split over multiple "
|
||||
"lines\"},{-1, 93463, \"world\"},{7, 5, \"!!\"},};",
|
||||
Style));
|
||||
|
||||
Style.ColumnLimit = 80;
|
||||
verifyFormat("test demo[] = {\n"
|
||||
" {56, 23, /* a comment */ \"hello\"},\n"
|
||||
" {-1, 93463, \"world\" },\n"
|
||||
" {7, 5, \"!!\" }\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("test demo[] = {\n"
|
||||
" {56, 23, \"hello\" },\n"
|
||||
" {-1, 93463, \"world\" /* comment here */},\n"
|
||||
" {7, 5, \"!!\" }\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
verifyFormat("test demo[] = {\n"
|
||||
" {56, /* a comment */ 23, \"hello\"},\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" {7, 5, \"!!\" }\n"
|
||||
"};\n",
|
||||
Style);
|
||||
|
||||
Style.ColumnLimit = 20;
|
||||
EXPECT_EQ(
|
||||
"demo = std::array<\n"
|
||||
" struct test, 3>{\n"
|
||||
" test{\n"
|
||||
" 56, 23,\n"
|
||||
" \"hello \"\n"
|
||||
" \"world i \"\n"
|
||||
" \"am a very \"\n"
|
||||
" \"long line \"\n"
|
||||
" \"that \"\n"
|
||||
" \"really, \"\n"
|
||||
" \"in any \"\n"
|
||||
" \"just \"\n"
|
||||
" \"world, \"\n"
|
||||
" \"ought to \"\n"
|
||||
" \"be split \"\n"
|
||||
" \"over \"\n"
|
||||
" \"multiple \"\n"
|
||||
" \"lines\"},\n"
|
||||
" test{-1, 93463,\n"
|
||||
" \"world\"},\n"
|
||||
" test{7, 5,\n"
|
||||
" \"!!\" },\n"
|
||||
"};",
|
||||
format("demo = std::array<struct test, 3>{test{56, 23, \"hello world "
|
||||
"i am a very long line that really, in any just world, ought "
|
||||
"to be split over multiple lines\"},test{-1, 93463, \"world\"},"
|
||||
"test{7, 5, \"!!\"},};",
|
||||
Style));
|
||||
|
||||
// This caused a core dump by enabling Alignment in the LLVMStyle globally
|
||||
Style = getLLVMStyleWithColumns(50);
|
||||
Style.AlignArrayOfStructures = FormatStyle::AIAS_Left;
|
||||
verifyFormat("static A x = {\n"
|
||||
" {{init1, init2, init3, init4},\n"
|
||||
" {init1, init2, init3, init4}}\n"
|
||||
"};",
|
||||
Style);
|
||||
Style.ColumnLimit = 100;
|
||||
EXPECT_EQ(
|
||||
"test demo[] = {\n"
|
||||
" {56, 23,\n"
|
||||
" \"hello world i am a very long line that really, in any just world"
|
||||
", ought to be split over \"\n"
|
||||
" \"multiple lines\" },\n"
|
||||
" {-1, 93463, \"world\"},\n"
|
||||
" {7, 5, \"!!\" },\n"
|
||||
"};",
|
||||
format("test demo[] = {{56, 23, \"hello world i am a very long line "
|
||||
"that really, in any just world, ought to be split over multiple "
|
||||
"lines\"},{-1, 93463, \"world\"},{7, 5, \"!!\"},};",
|
||||
Style));
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, UnderstandsPragmas) {
|
||||
verifyFormat("#pragma omp reduction(| : var)");
|
||||
verifyFormat("#pragma omp reduction(+ : var)");
|
||||
|
|
Loading…
Reference in New Issue