Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -1363,16 +1363,16 @@ /// See documentation of ``RawStringFormats``. struct RawStringFormat { - /// \brief The delimiter that this raw string format matches. - std::string Delimiter; /// \brief The language of this raw string. LanguageKind Language; + /// \brief A list of raw string delimiters that match this language. + std::vector Delimiters; /// \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 Delimiter == Other.Delimiter && Language == Other.Language && + return Language == Other.Language && Delimiters == Other.Delimiters && BasedOnStyle == Other.BasedOnStyle; } }; @@ -1383,16 +1383,29 @@ /// 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. + /// \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. /// /// To configure this in the .clang-format file, use: /// \code{.yaml} /// RawStringFormats: - /// - Delimiter: 'pb' - /// Language: TextProto - /// BasedOnStyle: llvm - /// - Delimiter: 'proto' - /// Language: TextProto - /// BasedOnStyle: google + /// - Language: TextProto + /// Delimiters: + /// - 'pb' + /// - 'proto' + /// BasedOnStyle: google + /// - Language: Cpp + /// Delimiters: + /// - 'cc' + /// - 'cpp' + /// BasedOnStyle: llvm /// \endcode std::vector RawStringFormats; Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -105,14 +105,21 @@ RawStringFormatStyleManager::RawStringFormatStyleManager( const FormatStyle &CodeStyle) { for (const auto &RawStringFormat : CodeStyle.RawStringFormats) { - FormatStyle Style; - if (!getPredefinedStyle(RawStringFormat.BasedOnStyle, - RawStringFormat.Language, &Style)) { - Style = getLLVMStyle(); - Style.Language = RawStringFormat.Language; + for (StringRef Delimiter : RawStringFormat.Delimiters) { + llvm::Optional LanguageStyle = + CodeStyle.GetLanguageStyle(RawStringFormat.Language); + if (!LanguageStyle) { + FormatStyle PredefinedStyle; + if (!getPredefinedStyle(RawStringFormat.BasedOnStyle, + RawStringFormat.Language, &PredefinedStyle)) { + PredefinedStyle = getLLVMStyle(); + PredefinedStyle.Language = RawStringFormat.Language; + } + LanguageStyle = PredefinedStyle; + } + LanguageStyle->ColumnLimit = CodeStyle.ColumnLimit; + DelimiterStyle.insert({Delimiter, *LanguageStyle}); } - Style.ColumnLimit = CodeStyle.ColumnLimit; - DelimiterStyle.insert({RawStringFormat.Delimiter, Style}); } } Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -455,8 +455,8 @@ template <> struct MappingTraits { static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) { - IO.mapOptional("Delimiter", Format.Delimiter); IO.mapOptional("Language", Format.Language); + IO.mapOptional("Delimiters", Format.Delimiters); IO.mapOptional("BasedOnStyle", Format.BasedOnStyle); } }; @@ -641,7 +641,6 @@ LLVMStyle.SpacesBeforeTrailingComments = 1; LLVMStyle.Standard = FormatStyle::LS_Cpp11; LLVMStyle.UseTab = FormatStyle::UT_Never; - LLVMStyle.RawStringFormats = {{"pb", FormatStyle::LK_TextProto, "google"}}; LLVMStyle.ReflowComments = true; LLVMStyle.SpacesInParentheses = false; LLVMStyle.SpacesInSquareBrackets = false; @@ -695,6 +694,19 @@ GoogleStyle.ObjCSpaceAfterProperty = false; GoogleStyle.ObjCSpaceBeforeProtocolList = false; GoogleStyle.PointerAlignment = FormatStyle::PAS_Left; + GoogleStyle.RawStringFormats = {{ + FormatStyle::LK_TextProto, + /*Delimiters=*/ + { + "pb", + "PB", + "proto", + "PROTO", + "textproto", + "TEXTPROTO", + }, + /*BasedOnStyle=*/"google", + }}; GoogleStyle.SpacesBeforeTrailingComments = 2; GoogleStyle.Standard = FormatStyle::LS_Auto; Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -10408,16 +10408,21 @@ Style.RawStringFormats.clear(); std::vector ExpectedRawStringFormats = { - {"pb", FormatStyle::LK_TextProto, "llvm"}, - {"cpp", FormatStyle::LK_Cpp, "google"}}; + {FormatStyle::LK_TextProto, {"pb", "proto"}, "llvm"}, + {FormatStyle::LK_Cpp, {"cc", "cpp"}, "google"}, + }; CHECK_PARSE("RawStringFormats:\n" - " - Delimiter: 'pb'\n" - " Language: TextProto\n" + " - Language: TextProto\n" + " Delimiters:\n" + " - 'pb'\n" + " - 'proto'\n" " BasedOnStyle: llvm\n" - " - Delimiter: 'cpp'\n" - " Language: Cpp\n" - " BasedOnStyle: google", + " - Language: Cpp\n" + " Delimiters:\n" + " - 'cc'\n" + " - 'cpp'\n" + " BasedOnStyle: google\n", RawStringFormats, ExpectedRawStringFormats); } Index: unittests/Format/FormatTestRawStrings.cpp =================================================================== --- unittests/Format/FormatTestRawStrings.cpp +++ unittests/Format/FormatTestRawStrings.cpp @@ -65,23 +65,23 @@ FormatStyle getRawStringPbStyleWithColumns(unsigned ColumnLimit) { FormatStyle Style = getLLVMStyle(); Style.ColumnLimit = ColumnLimit; - Style.RawStringFormats = {{/*Delimiter=*/"pb", - /*Kind=*/FormatStyle::LK_TextProto, + Style.RawStringFormats = {{/*Language=*/FormatStyle::LK_TextProto, + /*Delimiters=*/{"pb"}, /*BasedOnStyle=*/"google"}}; return Style; } FormatStyle getRawStringLLVMCppStyleBasedOn(std::string BasedOnStyle) { FormatStyle Style = getLLVMStyle(); - Style.RawStringFormats = {{/*Delimiter=*/"cpp", - /*Kind=*/FormatStyle::LK_Cpp, BasedOnStyle}}; + Style.RawStringFormats = {{/*Language=*/FormatStyle::LK_Cpp, + /*Delimiters=*/{"cpp"}, BasedOnStyle}}; return Style; } FormatStyle getRawStringGoogleCppStyleBasedOn(std::string BasedOnStyle) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp); - Style.RawStringFormats = {{/*Delimiter=*/"cpp", - /*Kind=*/FormatStyle::LK_Cpp, BasedOnStyle}}; + Style.RawStringFormats = {{/*Language=*/FormatStyle::LK_Cpp, + /*Delimiters=*/{"cpp"}, BasedOnStyle}}; return Style; } @@ -112,6 +112,21 @@ getRawStringGoogleCppStyleBasedOn("llvm"))); } +TEST_F(FormatTestRawStrings, UsesConfigurationOverBaseStyle) { + // llvm style puts '*' on the right. + // google style puts '*' on the left. + + // Uses the configured google style inside raw strings even if BasedOnStyle in + // the raw string format is llvm. + FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp); + EXPECT_EQ(0, parseConfiguration("---\n" + "Language: Cpp\n" + "BasedOnStyle: Google", &Style).value()); + 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)); +} + TEST_F(FormatTestRawStrings, MatchesDelimitersCaseSensitively) { // Don't touch the 'PB' raw string, format the 'pb' raw string. expect_eq(R"test( @@ -121,29 +136,6 @@ s = R"PB(item:1)PB"; t = R"pb(item:1)pb";)test", getRawStringPbStyleWithColumns(40))); - - FormatStyle MixedStyle = getLLVMStyle(); - MixedStyle.RawStringFormats = { - {/*Delimiter=*/"cpp", /*Kind=*/FormatStyle::LK_Cpp, - /*BasedOnStyle=*/"llvm"}, - {/*Delimiter=*/"CPP", /*Kind=*/FormatStyle::LK_Cpp, - /*BasedOnStyle=*/"google"}}; - - // Format the 'cpp' raw string with '*' on the right. - // Format the 'CPP' raw string with '*' on the left. - // Do not format the 'Cpp' raw string. - // Do not format non-raw strings. - expect_eq(R"test( -a = R"cpp(int *i = 0;)cpp"; -b = R"CPP(int* j = 0;)CPP"; -c = R"Cpp(int * k = 0;)Cpp"; -d = R"cpp(int * k = 0;)Cpp";)test", - format(R"test( -a = R"cpp(int * i = 0;)cpp"; -b = R"CPP(int * j = 0;)CPP"; -c = R"Cpp(int * k = 0;)Cpp"; -d = R"cpp(int * k = 0;)Cpp";)test", - MixedStyle)); } TEST_F(FormatTestRawStrings, ReformatsShortRawStringsOnSingleLine) {