summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorBirunthan Mohanathas <birunthan@mohanathas.com>2015-07-03 17:25:16 +0000
committerBirunthan Mohanathas <birunthan@mohanathas.com>2015-07-03 17:25:16 +0000
commitb001a0ba5e10937c3e1a6489bbd47889182cef69 (patch)
tree0b2d5b7fe9dae8714e0618094feedf1b414db98b /clang
parent15b86155c9e6d2eb6721eb4c613480fa8fe09f86 (diff)
downloadbcm5719-llvm-b001a0ba5e10937c3e1a6489bbd47889182cef69.tar.gz
bcm5719-llvm-b001a0ba5e10937c3e1a6489bbd47889182cef69.zip
clang-format: Add MacroBlock{Begin,End} options
The MacroBlockBegin and MacroBlockEnd options make matching macro identifiers behave like '{' and '}', respectively, in terms of indentation. Mozilla code, for example, uses several macros that begin and end a scope. Previously, Clang-Format removed the indentation resulting in: MACRO_BEGIN(...) MACRO_ENTRY(...) MACRO_ENTRY(...) MACRO_END Now, using the options MacroBlockBegin: "^[A-Z_]+_BEGIN$" MacroBlockEnd: "^[A-Z_]+_END$" will yield the expected result: MACRO_BEGIN(...) MACRO_ENTRY(...) MACRO_ENTRY(...) MACRO_END Differential Revision: http://reviews.llvm.org/D10840 llvm-svn: 241363
Diffstat (limited to 'clang')
-rw-r--r--clang/docs/ClangFormatStyleOptions.rst6
-rw-r--r--clang/include/clang/Format/Format.h8
-rw-r--r--clang/lib/Format/Format.cpp33
-rw-r--r--clang/lib/Format/FormatToken.h2
-rw-r--r--clang/lib/Format/UnwrappedLineParser.cpp34
-rw-r--r--clang/unittests/Format/FormatTest.cpp18
6 files changed, 91 insertions, 10 deletions
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index ab7bd872ca2..e80cfd545b0 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -394,6 +394,12 @@ the configuration (without a prefix: ``Auto``).
(https://developers.google.com/protocol-buffers/).
+**MacroBlockBegin** (``std::string``)
+ A regular expression matching macros that start a block.
+
+**MacroBlockEnd** (``std::string``)
+ A regular expression matching macros that end a block.
+
**MaxEmptyLinesToKeep** (``unsigned``)
The maximum number of consecutive empty lines to keep.
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 6f9523cdc1b..b234403bebc 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -290,6 +290,12 @@ struct FormatStyle {
/// \brief Language, this format style is targeted at.
LanguageKind Language;
+ /// \brief A regular expression matching macros that start a block.
+ std::string MacroBlockBegin;
+
+ /// \brief A regular expression matching macros that end a block.
+ std::string MacroBlockEnd;
+
/// \brief The maximum number of consecutive empty lines to keep.
unsigned MaxEmptyLinesToKeep;
@@ -479,6 +485,8 @@ struct FormatStyle {
IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
KeepEmptyLinesAtTheStartOfBlocks ==
R.KeepEmptyLinesAtTheStartOfBlocks &&
+ MacroBlockBegin == R.MacroBlockBegin &&
+ MacroBlockEnd == R.MacroBlockEnd &&
MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
NamespaceIndentation == R.NamespaceIndentation &&
ObjCBlockIndentWidth == R.ObjCBlockIndentWidth &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 2bbe4c63d15..1e7996e31ae 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -27,6 +27,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Regex.h"
#include "llvm/Support/YAMLTraits.h"
#include <queue>
#include <string>
@@ -244,6 +245,8 @@ template <> struct MappingTraits<FormatStyle> {
Style.IndentWrappedFunctionNames);
IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
Style.KeepEmptyLinesAtTheStartOfBlocks);
+ IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
+ IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
@@ -468,6 +471,8 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
ChromiumStyle.BinPackParameters = false;
ChromiumStyle.DerivePointerAlignment = false;
}
+ ChromiumStyle.MacroBlockBegin = "^IPC_BEGIN_MESSAGE_MAP$";
+ ChromiumStyle.MacroBlockBegin = "^IPC_END_MESSAGE_MAP$";
return ChromiumStyle;
}
@@ -620,7 +625,9 @@ public:
LessStashed(false), Column(0), TrailingWhitespace(0),
SourceMgr(SourceMgr), ID(ID), Style(Style),
IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable),
- Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false) {
+ Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false),
+ MacroBlockBeginRegex(Style.MacroBlockBegin),
+ MacroBlockEndRegex(Style.MacroBlockEnd) {
Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr,
getFormattingLangOpts(Style)));
Lex->SetKeepWhitespaceMode(true);
@@ -1168,12 +1175,21 @@ private:
Column = FormatTok->LastLineColumnWidth;
}
- if (!(Tokens.size() > 0 && Tokens.back()->Tok.getIdentifierInfo() &&
- Tokens.back()->Tok.getIdentifierInfo()->getPPKeywordID() ==
- tok::pp_define) &&
- std::find(ForEachMacros.begin(), ForEachMacros.end(),
- FormatTok->Tok.getIdentifierInfo()) != ForEachMacros.end())
- FormatTok->Type = TT_ForEachMacro;
+ if (Style.Language == FormatStyle::LK_Cpp) {
+ if (!(Tokens.size() > 0 && Tokens.back()->Tok.getIdentifierInfo() &&
+ Tokens.back()->Tok.getIdentifierInfo()->getPPKeywordID() ==
+ tok::pp_define) &&
+ std::find(ForEachMacros.begin(), ForEachMacros.end(),
+ FormatTok->Tok.getIdentifierInfo()) != ForEachMacros.end()) {
+ FormatTok->Type = TT_ForEachMacro;
+ } else if (FormatTok->is(tok::identifier)) {
+ if (MacroBlockBeginRegex.match(Text)) {
+ FormatTok->Type = TT_MacroBlockBegin;
+ } else if (MacroBlockEndRegex.match(Text)) {
+ FormatTok->Type = TT_MacroBlockEnd;
+ }
+ }
+ }
return FormatTok;
}
@@ -1198,6 +1214,9 @@ private:
bool FormattingDisabled;
+ llvm::Regex MacroBlockBeginRegex;
+ llvm::Regex MacroBlockEndRegex;
+
void readRawToken(FormatToken &Tok) {
Lex->LexFromRawLexer(Tok.Tok);
Tok.TokenText = StringRef(SourceMgr.getCharacterData(Tok.Tok.getLocation()),
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 5b7dadb8545..ed8a330843d 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -59,6 +59,8 @@ enum TokenType {
TT_LambdaLSquare,
TT_LeadingJavaAnnotation,
TT_LineComment,
+ TT_MacroBlockBegin,
+ TT_MacroBlockEnd,
TT_ObjCBlockLBrace,
TT_ObjCBlockLParen,
TT_ObjCDecl,
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index c58e6bccd9b..7fd07a269e3 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -269,7 +269,14 @@ void UnwrappedLineParser::parseFile() {
void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
bool SwitchLabelEncountered = false;
do {
- switch (FormatTok->Tok.getKind()) {
+ tok::TokenKind kind = FormatTok->Tok.getKind();
+ if (FormatTok->Type == TT_MacroBlockBegin) {
+ kind = tok::l_brace;
+ } else if (FormatTok->Type == TT_MacroBlockEnd) {
+ kind = tok::r_brace;
+ }
+
+ switch (kind) {
case tok::comment:
nextToken();
addUnwrappedLine();
@@ -393,10 +400,16 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
bool MunchSemi) {
- assert(FormatTok->Tok.is(tok::l_brace) && "'{' expected");
+ assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) &&
+ "'{' or macro block token expected");
+ const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
+
unsigned InitialLevel = Line->Level;
nextToken();
+ if (MacroBlock && FormatTok->is(tok::l_paren))
+ parseParens();
+
addUnwrappedLine();
ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
@@ -405,12 +418,17 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
++Line->Level;
parseLevel(/*HasOpeningBrace=*/true);
- if (!FormatTok->Tok.is(tok::r_brace)) {
+ if (MacroBlock ? !FormatTok->is(TT_MacroBlockEnd)
+ : !FormatTok->is(tok::r_brace)) {
Line->Level = InitialLevel;
return;
}
nextToken(); // Munch the closing brace.
+
+ if (MacroBlock && FormatTok->is(tok::l_paren))
+ parseParens();
+
if (MunchSemi && FormatTok->Tok.is(tok::semi))
nextToken();
Line->Level = InitialLevel;
@@ -757,6 +775,11 @@ void UnwrappedLineParser::parseStructuralElement() {
parseForOrWhileLoop();
return;
}
+ if (FormatTok->is(TT_MacroBlockBegin)) {
+ parseBlock(/*MustBeDeclaration=*/false, /*AddLevel=*/true,
+ /*MunchSemi=*/false);
+ return;
+ }
if (Style.Language == FormatStyle::LK_JavaScript &&
FormatTok->is(Keywords.kw_import)) {
parseJavaScriptEs6ImportExport();
@@ -860,6 +883,11 @@ void UnwrappedLineParser::parseStructuralElement() {
parseTryCatch();
return;
case tok::identifier: {
+ if (FormatTok->is(TT_MacroBlockEnd)) {
+ addUnwrappedLine();
+ return;
+ }
+
// Parse function literal unless 'function' is the first token in a line
// in which case this should be treated as a free-standing function.
if (Style.Language == FormatStyle::LK_JavaScript &&
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 0d85789a1dd..dfc88fa8f79 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -3216,6 +3216,24 @@ TEST_F(FormatTest, PutEmptyBlocksIntoOneLine) {
verifyFormat("enum E {}");
}
+TEST_F(FormatTest, FormatBeginBlockEndMacros) {
+ FormatStyle Style = getLLVMStyle();
+ Style.MacroBlockBegin = "^[A-Z_]+_BEGIN$";
+ Style.MacroBlockEnd = "^[A-Z_]+_END$";
+ verifyFormat("FOO_BEGIN\n"
+ " FOO_ENTRY\n"
+ "FOO_END", Style);
+ verifyFormat("FOO_BEGIN\n"
+ " NESTED_FOO_BEGIN\n"
+ " NESTED_FOO_ENTRY\n"
+ " NESTED_FOO_END\n"
+ "FOO_END", Style);
+ verifyFormat("FOO_BEGIN(Foo, Bar)\n"
+ " int x;\n"
+ " x = 1;\n"
+ "FOO_END(Baz)", Style);
+}
+
//===----------------------------------------------------------------------===//
// Line break tests.
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud