forked from OSchip/llvm-project
[clang-format] Add StatementAttributeLikeMacros option
This allows to ignore for example Qts emit when AlignConsecutiveDeclarations is set, otherwise it is parsed as a type and it results in some misformating: unsigned char MyChar = 'x'; emit signal(MyChar); Differential Revision: https://reviews.llvm.org/D93776
This commit is contained in:
parent
26a396c4ef
commit
bcc1dee600
|
@ -3074,6 +3074,20 @@ the configuration (without a prefix: ``Auto``).
|
|||
|
||||
|
||||
|
||||
**StatementAttributeLikeMacros** (``std::vector<std::string>``)
|
||||
Macros which are ignored in front of a statement, as if they were an
|
||||
attribute. So that they are not parsed as identifier, for example for Qts
|
||||
emit. \code
|
||||
AlignConsecutiveDeclarations: true
|
||||
StatementAttributeLikeMacros: []
|
||||
unsigned char data = 'x';
|
||||
emit signal(data); // This is parsed as variable declaration.
|
||||
|
||||
AlignConsecutiveDeclarations: true
|
||||
StatementAttributeLikeMacros: [emit]
|
||||
unsigned char data = 'x';
|
||||
emit signal(data); // Now it's fine again.
|
||||
|
||||
**StatementMacros** (``std::vector<std::string>``)
|
||||
A vector of macros that should be interpreted as complete
|
||||
statements.
|
||||
|
|
|
@ -296,6 +296,10 @@ clang-format
|
|||
- Option ``SpaceBeforeCaseColon`` has been added to add a space before the
|
||||
colon in a case or default statement.
|
||||
|
||||
- Option ``StatementAttributeLikeMacros`` has been added to declare
|
||||
macros which are not parsed as a type in front of a statement. See
|
||||
the documentation for an example.
|
||||
|
||||
|
||||
libclang
|
||||
--------
|
||||
|
|
|
@ -2676,6 +2676,21 @@ struct FormatStyle {
|
|||
/// \endcode
|
||||
LanguageStandard Standard;
|
||||
|
||||
/// Macros which are ignored in front of a statement, as if they were an
|
||||
/// attribute. So that they are not parsed as identifier, for example for Qts
|
||||
/// emit. \code
|
||||
/// AlignConsecutiveDeclarations: true
|
||||
/// StatementAttributeLikeMacros: []
|
||||
/// unsigned char data = 'x';
|
||||
/// emit signal(data); // This is parsed as variable declaration.
|
||||
///
|
||||
/// AlignConsecutiveDeclarations: true
|
||||
/// StatementAttributeLikeMacros: [emit]
|
||||
/// unsigned char data = 'x';
|
||||
/// emit signal(data); // Now it's fine again.
|
||||
/// \endcode
|
||||
std::vector<std::string> StatementAttributeLikeMacros;
|
||||
|
||||
/// The number of columns used for tab stops.
|
||||
unsigned TabWidth;
|
||||
|
||||
|
@ -2825,9 +2840,11 @@ struct FormatStyle {
|
|||
SpacesInSquareBrackets == R.SpacesInSquareBrackets &&
|
||||
SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets &&
|
||||
BitFieldColonSpacing == R.BitFieldColonSpacing &&
|
||||
Standard == R.Standard && TabWidth == R.TabWidth &&
|
||||
StatementMacros == R.StatementMacros && UseTab == R.UseTab &&
|
||||
UseCRLF == R.UseCRLF && TypenameMacros == R.TypenameMacros;
|
||||
Standard == R.Standard &&
|
||||
StatementAttributeLikeMacros == R.StatementAttributeLikeMacros &&
|
||||
StatementMacros == R.StatementMacros && TabWidth == R.TabWidth &&
|
||||
UseTab == R.UseTab && UseCRLF == R.UseCRLF &&
|
||||
TypenameMacros == R.TypenameMacros;
|
||||
}
|
||||
|
||||
llvm::Optional<FormatStyle> GetLanguageStyle(LanguageKind Language) const;
|
||||
|
|
|
@ -549,6 +549,8 @@ template <> struct MappingTraits<FormatStyle> {
|
|||
Style.ExperimentalAutoDetectBinPacking);
|
||||
IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
|
||||
IO.mapOptional("ForEachMacros", Style.ForEachMacros);
|
||||
IO.mapOptional("StatementAttributeLikeMacros",
|
||||
Style.StatementAttributeLikeMacros);
|
||||
IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
|
||||
IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
|
||||
IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
|
||||
|
@ -983,6 +985,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
|
|||
LLVMStyle.SortIncludes = true;
|
||||
LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
|
||||
LLVMStyle.SortUsingDeclarations = true;
|
||||
LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
|
||||
LLVMStyle.StatementMacros.push_back("Q_UNUSED");
|
||||
LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
|
||||
LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
|
||||
|
|
|
@ -96,6 +96,7 @@ namespace format {
|
|||
TYPE(RegexLiteral) \
|
||||
TYPE(SelectorName) \
|
||||
TYPE(StartOfName) \
|
||||
TYPE(StatementAttributeLikeMacro) \
|
||||
TYPE(StatementMacro) \
|
||||
TYPE(StructuredBindingLSquare) \
|
||||
TYPE(TemplateCloser) \
|
||||
|
|
|
@ -52,6 +52,10 @@ FormatTokenLexer::FormatTokenLexer(
|
|||
Macros.insert(
|
||||
{&IdentTable.get(WhitespaceSensitiveMacro), TT_UntouchableMacroFunc});
|
||||
}
|
||||
for (const std::string &StatementAttributeLikeMacro :
|
||||
Style.StatementAttributeLikeMacros)
|
||||
Macros.insert({&IdentTable.get(StatementAttributeLikeMacro),
|
||||
TT_StatementAttributeLikeMacro});
|
||||
}
|
||||
|
||||
ArrayRef<FormatToken *> FormatTokenLexer::lex() {
|
||||
|
|
|
@ -1368,7 +1368,8 @@ private:
|
|||
TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_JsFatArrow,
|
||||
TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator,
|
||||
TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral,
|
||||
TT_UntouchableMacroFunc, TT_ConstraintJunctions))
|
||||
TT_UntouchableMacroFunc, TT_ConstraintJunctions,
|
||||
TT_StatementAttributeLikeMacro))
|
||||
CurrentToken->setType(TT_Unknown);
|
||||
CurrentToken->Role.reset();
|
||||
CurrentToken->MatchingParen = nullptr;
|
||||
|
|
|
@ -655,6 +655,9 @@ void WhitespaceManager::alignConsecutiveDeclarations() {
|
|||
return true;
|
||||
if (C.Tok->isNot(TT_StartOfName))
|
||||
return false;
|
||||
if (C.Tok->Previous &&
|
||||
C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
|
||||
return false;
|
||||
// Check if there is a subsequent name that starts the same declaration.
|
||||
for (FormatToken *Next = C.Tok->Next; Next; Next = Next->Next) {
|
||||
if (Next->is(tok::comment))
|
||||
|
|
|
@ -14731,6 +14731,11 @@ TEST_F(FormatTest, ParsesConfiguration) {
|
|||
CHECK_PARSE("AttributeMacros: [attr1, attr2]", AttributeMacros,
|
||||
std::vector<std::string>({"attr1", "attr2"}));
|
||||
|
||||
Style.StatementAttributeLikeMacros.clear();
|
||||
CHECK_PARSE("StatementAttributeLikeMacros: [emit,Q_EMIT]",
|
||||
StatementAttributeLikeMacros,
|
||||
std::vector<std::string>({"emit", "Q_EMIT"}));
|
||||
|
||||
Style.StatementMacros.clear();
|
||||
CHECK_PARSE("StatementMacros: [QUNUSED]", StatementMacros,
|
||||
std::vector<std::string>{"QUNUSED"});
|
||||
|
@ -17803,6 +17808,36 @@ TEST_F(FormatTest, ConceptsAndRequires) {
|
|||
"struct constant;",
|
||||
Style);
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, StatementAttributeLikeMacros) {
|
||||
FormatStyle Style = getLLVMStyle();
|
||||
StringRef Source = "void Foo::slot() {\n"
|
||||
" unsigned char MyChar = 'x';\n"
|
||||
" emit signal(MyChar);\n"
|
||||
" Q_EMIT signal(MyChar);\n"
|
||||
"}";
|
||||
|
||||
EXPECT_EQ(Source, format(Source, Style));
|
||||
|
||||
Style.AlignConsecutiveDeclarations = true;
|
||||
EXPECT_EQ("void Foo::slot() {\n"
|
||||
" unsigned char MyChar = 'x';\n"
|
||||
" emit signal(MyChar);\n"
|
||||
" Q_EMIT signal(MyChar);\n"
|
||||
"}",
|
||||
format(Source, Style));
|
||||
|
||||
Style.StatementAttributeLikeMacros.push_back("emit");
|
||||
EXPECT_EQ(Source, format(Source, Style));
|
||||
|
||||
Style.StatementAttributeLikeMacros = {};
|
||||
EXPECT_EQ("void Foo::slot() {\n"
|
||||
" unsigned char MyChar = 'x';\n"
|
||||
" emit signal(MyChar);\n"
|
||||
" Q_EMIT signal(MyChar);\n"
|
||||
"}",
|
||||
format(Source, Style));
|
||||
}
|
||||
} // namespace
|
||||
} // namespace format
|
||||
} // namespace clang
|
||||
|
|
Loading…
Reference in New Issue