r322678 - [clang-format] adds enclosing function detection to raw string formatting
Krasimir Georgiev via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 17 08:17:26 PST 2018
Author: krasimir
Date: Wed Jan 17 08:17:26 2018
New Revision: 322678
URL: http://llvm.org/viewvc/llvm-project?rev=322678&view=rev
Log:
[clang-format] adds enclosing function detection to raw string formatting
Summary: This patch adds enclosing function detection to raw string formatting.
Reviewers: bkramer
Reviewed By: bkramer
Subscribers: klimek, cfe-commits
Differential Revision: https://reviews.llvm.org/D42167
Modified:
cfe/trunk/docs/ClangFormatStyleOptions.rst
cfe/trunk/include/clang/Format/Format.h
cfe/trunk/lib/Format/ContinuationIndenter.cpp
cfe/trunk/lib/Format/ContinuationIndenter.h
cfe/trunk/lib/Format/Format.cpp
cfe/trunk/unittests/Format/FormatTest.cpp
cfe/trunk/unittests/Format/FormatTestRawStrings.cpp
Modified: cfe/trunk/docs/ClangFormatStyleOptions.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ClangFormatStyleOptions.rst?rev=322678&r1=322677&r2=322678&view=diff
==============================================================================
--- cfe/trunk/docs/ClangFormatStyleOptions.rst (original)
+++ cfe/trunk/docs/ClangFormatStyleOptions.rst Wed Jan 17 08:17:26 2018
@@ -994,9 +994,9 @@ the configuration (without a prefix: ``A
.. code-block:: c++
- Constructor()
- : initializer1(),
- initializer2()
+ Constructor()
+ : initializer1(),
+ initializer2()
* ``BCIS_BeforeComma`` (in configuration: ``BeforeComma``)
Break constructor initializers before the colon and commas, and align
@@ -1004,18 +1004,18 @@ the configuration (without a prefix: ``A
.. code-block:: c++
- Constructor()
- : initializer1()
- , initializer2()
+ Constructor()
+ : initializer1()
+ , initializer2()
* ``BCIS_AfterColon`` (in configuration: ``AfterColon``)
Break constructor initializers after the colon and commas.
.. code-block:: c++
- Constructor() :
- initializer1(),
- initializer2()
+ Constructor() :
+ initializer1(),
+ initializer2()
@@ -1201,7 +1201,8 @@ the configuration (without a prefix: ``A
* ``IBS_Regroup`` (in configuration: ``Regroup``)
Merge multiple ``#include`` blocks together and sort as one.
- Then split into groups based on category priority. See ``IncludeCategories``.
+ Then split into groups based on category priority. See
+ ``IncludeCategories``.
.. code-block:: c++
@@ -1577,24 +1578,38 @@ the configuration (without a prefix: ``A
**RawStringFormats** (``std::vector<RawStringFormat>``)
- Raw string delimiters denoting that the raw string contents are
- code in a particular language and can be reformatted.
+ Defines hints for detecting supported languages code blocks in raw
+ strings.
+
+ A raw string with a matching delimiter or a matching enclosing function
+ name will be reformatted assuming the specified language based on the
+ style for that language defined in the .clang-format file. If no style has
+ been defined in the .clang-format file for the specific language, a
+ predefined style given by 'BasedOnStyle' is used. If 'BasedOnStyle' is not
+ found, the formatting is based on llvm style. A matching delimiter takes
+ precedence over a matching enclosing function name for determining the
+ language of the raw string contents.
- A raw string with a matching delimiter will be reformatted assuming the
- specified language based on a predefined style given by 'BasedOnStyle'.
- If 'BasedOnStyle' is not found, the formatting is based on llvm style.
+ There should be at most one specification per language and each delimiter
+ and enclosing function should not occur in multiple specifications.
To configure this in the .clang-format file, use:
.. code-block:: yaml
RawStringFormats:
- - Delimiter: 'pb'
- Language: TextProto
- BasedOnStyle: llvm
- - Delimiter: 'proto'
- Language: TextProto
- BasedOnStyle: google
+ - Language: TextProto
+ Delimiters:
+ - 'pb'
+ - 'proto'
+ EnclosingFunctions:
+ - 'PARSE_TEXT_PROTO'
+ BasedOnStyle: google
+ - Language: Cpp
+ Delimiters:
+ - 'cc'
+ - 'cpp'
+ BasedOnStyle: llvm
**ReflowComments** (``bool``)
If ``true``, clang-format will attempt to re-flow comments.
Modified: cfe/trunk/include/clang/Format/Format.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=322678&r1=322677&r2=322678&view=diff
==============================================================================
--- cfe/trunk/include/clang/Format/Format.h (original)
+++ cfe/trunk/include/clang/Format/Format.h Wed Jan 17 08:17:26 2018
@@ -1367,12 +1367,15 @@ struct FormatStyle {
LanguageKind Language;
/// \brief A list of raw string delimiters that match this language.
std::vector<std::string> Delimiters;
+ /// \brief A list of enclosing function names that match this language.
+ std::vector<std::string> EnclosingFunctions;
/// \brief The style name on which this raw string format is based on.
/// If not specified, the raw string format is based on the style that this
/// format is based on.
std::string BasedOnStyle;
bool operator==(const RawStringFormat &Other) const {
return Language == Other.Language && Delimiters == Other.Delimiters &&
+ EnclosingFunctions == Other.EnclosingFunctions &&
BasedOnStyle == Other.BasedOnStyle;
}
};
@@ -1380,12 +1383,17 @@ struct FormatStyle {
/// \brief Defines hints for detecting supported languages code blocks in raw
/// strings.
///
- /// A raw string with a matching delimiter will be reformatted assuming the
- /// specified language based on the style for that language defined in the
- /// .clang-format file. If no style has been defined in the .clang-format file
- /// for the specific language, a predefined style given by 'BasedOnStyle' is
- /// used. If 'BasedOnStyle' is not found, the formatting is based on llvm
- /// style.
+ /// A raw string with a matching delimiter or a matching enclosing function
+ /// name will be reformatted assuming the specified language based on the
+ /// style for that language defined in the .clang-format file. If no style has
+ /// been defined in the .clang-format file for the specific language, a
+ /// predefined style given by 'BasedOnStyle' is used. If 'BasedOnStyle' is not
+ /// found, the formatting is based on llvm style. A matching delimiter takes
+ /// precedence over a matching enclosing function name for determining the
+ /// language of the raw string contents.
+ ///
+ /// There should be at most one specification per language and each delimiter
+ /// and enclosing function should not occur in multiple specifications.
///
/// To configure this in the .clang-format file, use:
/// \code{.yaml}
@@ -1394,6 +1402,8 @@ struct FormatStyle {
/// Delimiters:
/// - 'pb'
/// - 'proto'
+ /// EnclosingFunctions:
+ /// - 'PARSE_TEXT_PROTO'
/// BasedOnStyle: google
/// - Language: Cpp
/// Delimiters:
Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=322678&r1=322677&r2=322678&view=diff
==============================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Wed Jan 17 08:17:26 2018
@@ -105,32 +105,44 @@ static llvm::Optional<StringRef> getRawS
RawStringFormatStyleManager::RawStringFormatStyleManager(
const FormatStyle &CodeStyle) {
for (const auto &RawStringFormat : CodeStyle.RawStringFormats) {
- for (StringRef Delimiter : RawStringFormat.Delimiters) {
- llvm::Optional<FormatStyle> LanguageStyle =
- CodeStyle.GetLanguageStyle(RawStringFormat.Language);
- if (!LanguageStyle) {
- FormatStyle PredefinedStyle;
- if (!getPredefinedStyle(RawStringFormat.BasedOnStyle,
- RawStringFormat.Language, &PredefinedStyle)) {
- PredefinedStyle = getLLVMStyle();
- PredefinedStyle.Language = RawStringFormat.Language;
- }
- LanguageStyle = PredefinedStyle;
+ llvm::Optional<FormatStyle> LanguageStyle =
+ CodeStyle.GetLanguageStyle(RawStringFormat.Language);
+ if (!LanguageStyle) {
+ FormatStyle PredefinedStyle;
+ if (!getPredefinedStyle(RawStringFormat.BasedOnStyle,
+ RawStringFormat.Language, &PredefinedStyle)) {
+ PredefinedStyle = getLLVMStyle();
+ PredefinedStyle.Language = RawStringFormat.Language;
}
- LanguageStyle->ColumnLimit = CodeStyle.ColumnLimit;
+ LanguageStyle = PredefinedStyle;
+ }
+ LanguageStyle->ColumnLimit = CodeStyle.ColumnLimit;
+ for (StringRef Delimiter : RawStringFormat.Delimiters) {
DelimiterStyle.insert({Delimiter, *LanguageStyle});
}
+ for (StringRef EnclosingFunction : RawStringFormat.EnclosingFunctions) {
+ EnclosingFunctionStyle.insert({EnclosingFunction, *LanguageStyle});
+ }
}
}
llvm::Optional<FormatStyle>
-RawStringFormatStyleManager::get(StringRef Delimiter) const {
+RawStringFormatStyleManager::getDelimiterStyle(StringRef Delimiter) const {
auto It = DelimiterStyle.find(Delimiter);
if (It == DelimiterStyle.end())
return None;
return It->second;
}
+llvm::Optional<FormatStyle>
+RawStringFormatStyleManager::getEnclosingFunctionStyle(
+ StringRef EnclosingFunction) const {
+ auto It = EnclosingFunctionStyle.find(EnclosingFunction);
+ if (It == EnclosingFunctionStyle.end())
+ return None;
+ return It->second;
+}
+
ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,
const AdditionalKeywords &Keywords,
const SourceManager &SourceMgr,
@@ -1437,6 +1449,26 @@ unsigned ContinuationIndenter::handleEnd
return Penalty;
}
+// Returns the enclosing function name of a token, or the empty string if not
+// found.
+static StringRef getEnclosingFunctionName(const FormatToken &Current) {
+ // Look for: 'function(' or 'function<templates>(' before Current.
+ auto Tok = Current.getPreviousNonComment();
+ if (!Tok || !Tok->is(tok::l_paren))
+ return "";
+ Tok = Tok->getPreviousNonComment();
+ if (!Tok)
+ return "";
+ if (Tok->is(TT_TemplateCloser)) {
+ Tok = Tok->MatchingParen;
+ if (Tok)
+ Tok = Tok->getPreviousNonComment();
+ }
+ if (!Tok || !Tok->is(tok::identifier))
+ return "";
+ return Tok->TokenText;
+}
+
llvm::Optional<FormatStyle>
ContinuationIndenter::getRawStringStyle(const FormatToken &Current,
const LineState &State) {
@@ -1445,7 +1477,10 @@ ContinuationIndenter::getRawStringStyle(
auto Delimiter = getRawStringDelimiter(Current.TokenText);
if (!Delimiter)
return None;
- auto RawStringStyle = RawStringFormats.get(*Delimiter);
+ auto RawStringStyle = RawStringFormats.getDelimiterStyle(*Delimiter);
+ if (!RawStringStyle)
+ RawStringStyle = RawStringFormats.getEnclosingFunctionStyle(
+ getEnclosingFunctionName(Current));
if (!RawStringStyle)
return None;
RawStringStyle->ColumnLimit = getColumnLimit(State);
Modified: cfe/trunk/lib/Format/ContinuationIndenter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.h?rev=322678&r1=322677&r2=322678&view=diff
==============================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.h (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.h Wed Jan 17 08:17:26 2018
@@ -38,10 +38,14 @@ class WhitespaceManager;
struct RawStringFormatStyleManager {
llvm::StringMap<FormatStyle> DelimiterStyle;
+ llvm::StringMap<FormatStyle> EnclosingFunctionStyle;
RawStringFormatStyleManager(const FormatStyle &CodeStyle);
- llvm::Optional<FormatStyle> get(StringRef Delimiter) const;
+ llvm::Optional<FormatStyle> getDelimiterStyle(StringRef Delimiter) const;
+
+ llvm::Optional<FormatStyle>
+ getEnclosingFunctionStyle(StringRef EnclosingFunction) const;
};
class ContinuationIndenter {
Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=322678&r1=322677&r2=322678&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Wed Jan 17 08:17:26 2018
@@ -457,6 +457,7 @@ template <> struct MappingTraits<FormatS
static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
IO.mapOptional("Language", Format.Language);
IO.mapOptional("Delimiters", Format.Delimiters);
+ IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
}
};
@@ -705,6 +706,12 @@ FormatStyle getGoogleStyle(FormatStyle::
"textproto",
"TEXTPROTO",
},
+ /*EnclosingFunctionNames=*/
+ {
+ "EqualsProto",
+ "PARSE_TEXT_PROTO",
+ "ParseTextProto",
+ },
/*BasedOnStyle=*/"google",
}};
GoogleStyle.SpacesBeforeTrailingComments = 2;
Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=322678&r1=322677&r2=322678&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Wed Jan 17 08:17:26 2018
@@ -10408,8 +10408,18 @@ TEST_F(FormatTest, ParsesConfiguration)
Style.RawStringFormats.clear();
std::vector<FormatStyle::RawStringFormat> ExpectedRawStringFormats = {
- {FormatStyle::LK_TextProto, {"pb", "proto"}, "llvm"},
- {FormatStyle::LK_Cpp, {"cc", "cpp"}, "google"},
+ {
+ FormatStyle::LK_TextProto,
+ {"pb", "proto"},
+ {"PARSE_TEXT_PROTO"},
+ "llvm",
+ },
+ {
+ FormatStyle::LK_Cpp,
+ {"cc", "cpp"},
+ {"C_CODEBLOCK", "CPPEVAL"},
+ "",
+ },
};
CHECK_PARSE("RawStringFormats:\n"
@@ -10417,12 +10427,16 @@ TEST_F(FormatTest, ParsesConfiguration)
" Delimiters:\n"
" - 'pb'\n"
" - 'proto'\n"
+ " EnclosingFunctions:\n"
+ " - 'PARSE_TEXT_PROTO'\n"
" BasedOnStyle: llvm\n"
" - Language: Cpp\n"
" Delimiters:\n"
" - 'cc'\n"
" - 'cpp'\n"
- " BasedOnStyle: google\n",
+ " EnclosingFunctions:\n"
+ " - 'C_CODEBLOCK'\n"
+ " - 'CPPEVAL'\n",
RawStringFormats, ExpectedRawStringFormats);
}
Modified: cfe/trunk/unittests/Format/FormatTestRawStrings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestRawStrings.cpp?rev=322678&r1=322677&r2=322678&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTestRawStrings.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestRawStrings.cpp Wed Jan 17 08:17:26 2018
@@ -65,23 +65,32 @@ protected:
FormatStyle getRawStringPbStyleWithColumns(unsigned ColumnLimit) {
FormatStyle Style = getLLVMStyle();
Style.ColumnLimit = ColumnLimit;
- Style.RawStringFormats = {{/*Language=*/FormatStyle::LK_TextProto,
- /*Delimiters=*/{"pb"},
- /*BasedOnStyle=*/"google"}};
+ Style.RawStringFormats = {
+ {/*Language=*/FormatStyle::LK_TextProto,
+ /*Delimiters=*/{"pb"},
+ /*EnclosingFunctions=*/{},
+ /*BasedOnStyle=*/"google"},
+ };
return Style;
}
FormatStyle getRawStringLLVMCppStyleBasedOn(std::string BasedOnStyle) {
FormatStyle Style = getLLVMStyle();
- Style.RawStringFormats = {{/*Language=*/FormatStyle::LK_Cpp,
- /*Delimiters=*/{"cpp"}, BasedOnStyle}};
+ Style.RawStringFormats = {
+ {/*Language=*/FormatStyle::LK_Cpp,
+ /*Delimiters=*/{"cpp"},
+ /*EnclosingFunctions=*/{}, BasedOnStyle},
+ };
return Style;
}
FormatStyle getRawStringGoogleCppStyleBasedOn(std::string BasedOnStyle) {
FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp);
- Style.RawStringFormats = {{/*Language=*/FormatStyle::LK_Cpp,
- /*Delimiters=*/{"cpp"}, BasedOnStyle}};
+ Style.RawStringFormats = {
+ {/*Language=*/FormatStyle::LK_Cpp,
+ /*Delimiters=*/{"cpp"},
+ /*EnclosingFunctions=*/{}, BasedOnStyle},
+ };
return Style;
}
@@ -122,7 +131,7 @@ TEST_F(FormatTestRawStrings, UsesConfigu
EXPECT_EQ(0, parseConfiguration("---\n"
"Language: Cpp\n"
"BasedOnStyle: Google", &Style).value());
- Style.RawStringFormats = {{FormatStyle::LK_Cpp, {"cpp"}, "llvm"}};
+ Style.RawStringFormats = {{FormatStyle::LK_Cpp, {"cpp"}, {}, "llvm"}};
expect_eq(R"test(int* i = R"cpp(int* j = 0;)cpp";)test",
format(R"test(int * i = R"cpp(int * j = 0;)cpp";)test", Style));
}
@@ -720,6 +729,29 @@ TEST_F(FormatTestRawStrings, DontFormatN
getRawStringPbStyleWithColumns(20)));
}
+TEST_F(FormatTestRawStrings, FormatsRawStringsWithEnclosingFunctionName) {
+ FormatStyle Style = getRawStringPbStyleWithColumns(40);
+ Style.RawStringFormats[0].EnclosingFunctions.push_back(
+ "PARSE_TEXT_PROTO");
+ Style.RawStringFormats[0].EnclosingFunctions.push_back("ParseTextProto");
+ expect_eq(R"test(a = PARSE_TEXT_PROTO(R"(key: value)");)test",
+ format(R"test(a = PARSE_TEXT_PROTO(R"(key:value)");)test", Style));
+
+ expect_eq(R"test(
+a = PARSE_TEXT_PROTO /**/ (
+ /**/ R"(key: value)");)test",
+ format(R"test(
+a = PARSE_TEXT_PROTO/**/(/**/R"(key:value)");)test",
+ Style));
+
+ expect_eq(R"test(
+a = ParseTextProto<ProtoType>(
+ R"(key: value)");)test",
+ format(R"test(
+a = ParseTextProto<ProtoType>(R"(key:value)");)test",
+ Style));
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
More information about the cfe-commits
mailing list