bersbersbers updated this revision to Diff 506357. bersbersbers added a comment.
Fix unit tests, add unit tests CHANGES SINCE LAST ACTION https://reviews.llvm.org/D145435/new/ https://reviews.llvm.org/D145435 Files: clang/docs/ClangFormatStyleOptions.rst clang/include/clang/Format/Format.h clang/lib/Format/BreakableToken.cpp clang/lib/Format/BreakableToken.h clang/lib/Format/ContinuationIndenter.cpp clang/lib/Format/Format.cpp clang/lib/Format/UnwrappedLineParser.cpp clang/unittests/Format/ConfigParseTest.cpp
Index: clang/unittests/Format/ConfigParseTest.cpp =================================================================== --- clang/unittests/Format/ConfigParseTest.cpp +++ clang/unittests/Format/ConfigParseTest.cpp @@ -1262,6 +1262,22 @@ "none", "", &FS); ASSERT_TRUE(static_cast<bool>(Style9)); ASSERT_EQ(*Style9, SubSubStyle); + + // Test 10.1: use style from style comment in code file. + ASSERT_TRUE( + FS.addFile("comment.cpp", 0, llvm::MemoryBuffer::getMemBuffer(""))); + auto Style10 = getStyle("file", "comment.cpp", "LLVM", + " // clang-format style=Google", &FS); + ASSERT_TRUE((bool)Style10); + ASSERT_EQ(*Style10, getGoogleStyle()); + + // Test 10.2: don't use commented style comment. + ASSERT_TRUE( + FS.addFile("comment.cpp", 0, llvm::MemoryBuffer::getMemBuffer(""))); + Style10 = getStyle("file", "comment.cpp", "LLVM", + "// // clang-format style=Google", &FS); + ASSERT_TRUE((bool)Style10); + ASSERT_EQ(*Style10, getLLVMStyle()); } TEST(ConfigParseTest, GetStyleOfSpecificFile) { Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -4292,6 +4292,10 @@ if (CommentPragmasRegex.match(IndentContent)) return false; + // If comment is a style comment, treat as separate section. + if (IndentContent.ltrim().startswith(clang::format::StyleComment)) + return false; + // If Line starts with a line comment, then FormatTok continues the comment // section if its original column is greater or equal to the original start // column of the line. Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -3741,6 +3741,29 @@ if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) return make_string_error("Invalid fallback style \"" + FallbackStyleName); + if (StyleName == "file") { + // Read style from first style comment at start of line in the code. + std::string Prefix{std::string("// ") + StyleComment}; + size_t PrefixPos = StringRef::npos; + while ((PrefixPos = Code.find(Prefix, PrefixPos + 1)) != StringRef::npos) { + // For each prefix, locate respective start of line (SoL) and check text + // between prefix and start of line for non-whitespace (comments not at + // start of line up to whitespace may be quoted, commented out, ...). + if (const size_t SoL = Code.substr(0, PrefixPos).find_last_of("\r\n") + 1; + !Code.substr(SoL, PrefixPos - SoL).ltrim().empty()) { + continue; + } + + // Use remainder of line as `StyleName` as if passed by `-style=...`; + // if no end of line (EoL) found, use remainder of file. + const size_t StylePos = PrefixPos + Prefix.size(); + const size_t EoL = Code.find_first_of("\r\n", StylePos); + const size_t StyleLen = EoL - (EoL == StringRef::npos ? 0 : StylePos); + StyleName = Code.substr(StylePos, StyleLen); + break; + } + } + llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply; Index: clang/lib/Format/ContinuationIndenter.cpp =================================================================== --- clang/lib/Format/ContinuationIndenter.cpp +++ clang/lib/Format/ContinuationIndenter.cpp @@ -2192,7 +2192,7 @@ }(); if (!Style.ReflowComments || CommentPragmasRegex.match(Current.TokenText.substr(2)) || - switchesFormatting(Current) || !RegularComments) { + setsStyle(Current) || switchesFormatting(Current) || !RegularComments) { return nullptr; } return std::make_unique<BreakableLineCommentSection>( Index: clang/lib/Format/BreakableToken.h =================================================================== --- clang/lib/Format/BreakableToken.h +++ clang/lib/Format/BreakableToken.h @@ -27,6 +27,10 @@ namespace clang { namespace format { +/// Checks if \p Token sets style, basically, // clang-format style=.... +/// \p Token must be a line comment. +bool setsStyle(const FormatToken &Token); + /// Checks if \p Token switches formatting, like /* clang-format off */. /// \p Token must be a comment. bool switchesFormatting(const FormatToken &Token); Index: clang/lib/Format/BreakableToken.cpp =================================================================== --- clang/lib/Format/BreakableToken.cpp +++ clang/lib/Format/BreakableToken.cpp @@ -216,6 +216,12 @@ return BreakableToken::Split(StringRef::npos, 0); } +bool setsStyle(const FormatToken &Token) { + assert(Token.is(TT_LineComment) && "style is set by line-comment token"); + StringRef Content = Token.TokenText.substr(2).ltrim(); + return Content.startswith(StyleComment); +} + bool switchesFormatting(const FormatToken &Token) { assert((Token.is(TT_BlockComment) || Token.is(TT_LineComment)) && "formatting regions are switched by comment tokens"); @@ -339,7 +345,7 @@ // Lines starting with '-', '-#', '+' or '*' are bulleted/numbered lists. bool hasSpecialMeaningPrefix = false; for (StringRef Prefix : - {"@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* "}) { + {"@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* ", StyleComment}) { if (Content.startswith(Prefix)) { hasSpecialMeaningPrefix = true; break; @@ -834,12 +840,13 @@ assert(Lines[i].size() > IndentPrefix.size()); const auto FirstNonSpace = Lines[i][IndentPrefix.size()]; + const bool IsStyleComment = LineTok && setsStyle(*LineTok); const bool IsFormatComment = LineTok && switchesFormatting(*LineTok); const bool LineRequiresLeadingSpace = !NoSpaceBeforeFirstCommentChar() || (FirstNonSpace == '}' && FirstLineSpaceChange != 0); const bool AllowsSpaceChange = - !IsFormatComment && + !IsStyleComment && !IsFormatComment && (SpacesInPrefix != 0 || LineRequiresLeadingSpace); if (PrefixSpaceChange[i] > 0 && AllowsSpaceChange) { @@ -1048,6 +1055,7 @@ // We do reflow in that case in block comments. return LineIndex > 0 && !CommentPragmasRegex.match(IndentContent) && mayReflowContent(Content[LineIndex]) && !Tok.Finalized && + !setsStyle(tokenAt(LineIndex)) && !switchesFormatting(tokenAt(LineIndex)) && OriginalPrefix[LineIndex] == OriginalPrefix[LineIndex - 1]; } Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -4651,6 +4651,9 @@ bool isClangFormatOn(StringRef Comment); bool isClangFormatOff(StringRef Comment); +// Contents of style comments to set style within code files. +constexpr char const *StyleComment{"clang-format style="}; + } // end namespace format } // end namespace clang Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -28,12 +28,16 @@ Configuring Style with clang-format =================================== -:program:`clang-format` supports two ways to provide custom style options: +:program:`clang-format` supports three ways to provide custom style options: directly specify style configuration in the ``-style=`` command line option or -use ``-style=file`` and put style configuration in the ``.clang-format`` or +use ``-style=file`` and put style configuration either in a style comment +(``// clang-format style=``) in each code file or in the ``.clang-format`` or ``_clang-format`` file in the project directory. When using ``-style=file``, :program:`clang-format` for each input file will +locate the first ``// clang-format style=`` style comment at the start of a line +(ignoring preceding whitespace), and use the remainder of that line as the +style for this whole file; only if no such style comment can be found, it will try to find the ``.clang-format`` file located in the closest parent directory of the input file. When the standard input is used, the search is started from the current directory. @@ -106,6 +110,18 @@ -style='{key1: value1, key2: value2, ...}' +Similar syntax be used within the file, such as + +.. code-block:: console + + // clang-format style={key1: value1, key2: value2, ...} + +or even + +.. code-block:: console + + // clang-format style=file:<format_file_path> + Disabling Formatting on a Piece of Code =======================================
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits