Author: Owen Pan Date: 2023-02-01T13:07:09-08:00 New Revision: 25e2d0f3c803e4d71f7ef4893b5d023d252b283f
URL: https://github.com/llvm/llvm-project/commit/25e2d0f3c803e4d71f7ef4893b5d023d252b283f DIFF: https://github.com/llvm/llvm-project/commit/25e2d0f3c803e4d71f7ef4893b5d023d252b283f.diff LOG: [clang-format] Support clang-format on/off line comments as prefix Closes #60264. Differential Revision: https://reviews.llvm.org/D142804 Added: Modified: clang/docs/ClangFormatStyleOptions.rst clang/include/clang/Format/Format.h clang/lib/Format/Format.cpp clang/lib/Format/FormatTokenLexer.cpp clang/lib/Format/IntegerLiteralSeparatorFixer.cpp clang/lib/Format/SortJavaScriptImports.cpp clang/unittests/Format/FormatTest.cpp Removed: ################################################################################ diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index da5af2645f18..8f5bb78b90bb 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -113,8 +113,10 @@ Disabling Formatting on a Piece of Code Clang-format understands also special comments that switch formatting in a delimited range. The code between a comment ``// clang-format off`` or ``/* clang-format off */`` up to a comment ``// clang-format on`` or -``/* clang-format on */`` will not be formatted. The comments themselves -will be formatted (aligned) normally. +``/* clang-format on */`` will not be formatted. The comments themselves will be +formatted (aligned) normally. Also, a colon (``:``) and additional text may +follow ``// clang-format off`` or `` clang-format on`` to explain why +clang-format is turned off or back on. .. code-block:: c++ diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 72efd3be1cc7..b5f9b8b955a7 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -4599,6 +4599,9 @@ inline StringRef getLanguageName(FormatStyle::LanguageKind Language) { } } +bool isClangFormatOn(StringRef Comment); +bool isClangFormatOff(StringRef Comment); + } // end namespace format } // end namespace clang diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index f37c3f983635..ea2075762575 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -3002,13 +3002,10 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, if (Trimmed.contains(RawStringTermination)) FormattingOff = false; - if (Trimmed == "// clang-format off" || - Trimmed == "/* clang-format off */") { + if (isClangFormatOff(Trimmed)) FormattingOff = true; - } else if (Trimmed == "// clang-format on" || - Trimmed == "/* clang-format on */") { + else if (isClangFormatOn(Trimmed)) FormattingOff = false; - } const bool EmptyLineSkipped = Trimmed.empty() && @@ -3185,9 +3182,9 @@ tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); StringRef Trimmed = Line.trim(); - if (Trimmed == "// clang-format off") + if (isClangFormatOff(Trimmed)) FormattingOff = true; - else if (Trimmed == "// clang-format on") + else if (isClangFormatOn(Trimmed)) FormattingOff = false; if (ImportRegex.match(Line, &Matches)) { @@ -3893,5 +3890,25 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, return FallbackStyle; } +static bool isClangFormatOnOff(StringRef Comment, bool On) { + if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */")) + return true; + + static const char ClangFormatOn[] = "// clang-format on"; + static const char ClangFormatOff[] = "// clang-format off"; + const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1; + + return Comment.startswith(On ? ClangFormatOn : ClangFormatOff) && + (Comment.size() == Size || Comment[Size] == ':'); +} + +bool isClangFormatOn(StringRef Comment) { + return isClangFormatOnOff(Comment, /*On=*/true); +} + +bool isClangFormatOff(StringRef Comment) { + return isClangFormatOnOff(Comment, /*On=*/false); +} + } // namespace format } // namespace clang diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index f8f5f7112188..f06f9fb9949d 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -1286,17 +1286,13 @@ void FormatTokenLexer::readRawToken(FormatToken &Tok) { Tok.Tok.setKind(tok::string_literal); } - if (Tok.is(tok::comment) && (Tok.TokenText == "// clang-format on" || - Tok.TokenText == "/* clang-format on */")) { + if (Tok.is(tok::comment) && isClangFormatOn(Tok.TokenText)) FormattingDisabled = false; - } Tok.Finalized = FormattingDisabled; - if (Tok.is(tok::comment) && (Tok.TokenText == "// clang-format off" || - Tok.TokenText == "/* clang-format off */")) { + if (Tok.is(tok::comment) && isClangFormatOff(Tok.TokenText)) FormattingDisabled = true; - } } void FormatTokenLexer::resetLexer(unsigned Offset) { diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp index ef07ab06760b..24e758e986cf 100644 --- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp +++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp @@ -87,9 +87,9 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env, auto Location = Tok.getLocation(); auto Text = StringRef(SourceMgr.getCharacterData(Location), Length); if (Tok.is(tok::comment)) { - if (Text == "// clang-format off" || Text == "/* clang-format off */") + if (isClangFormatOff(Text)) Skip = true; - else if (Text == "// clang-format on" || Text == "/* clang-format on */") + else if (isClangFormatOn(Text)) Skip = false; continue; } diff --git a/clang/lib/Format/SortJavaScriptImports.cpp b/clang/lib/Format/SortJavaScriptImports.cpp index c9de4868bf84..ce83ddea3e07 100644 --- a/clang/lib/Format/SortJavaScriptImports.cpp +++ b/clang/lib/Format/SortJavaScriptImports.cpp @@ -195,8 +195,7 @@ class JavaScriptImportSorter : public TokenAnalyzer { // Separate references from the main code body of the file. if (FirstNonImportLine && FirstNonImportLine->First->NewlinesBefore < 2 && !(FirstNonImportLine->First->is(tok::comment) && - FirstNonImportLine->First->TokenText.trim() == - "// clang-format on")) { + isClangFormatOn(FirstNonImportLine->First->TokenText.trim()))) { ReferencesText += "\n"; } @@ -376,9 +375,9 @@ class JavaScriptImportSorter : public TokenAnalyzer { // This is tracked in FormattingOff here and on JsModuleReference. while (Current && Current->is(tok::comment)) { StringRef CommentText = Current->TokenText.trim(); - if (CommentText == "// clang-format off") { + if (isClangFormatOff(CommentText)) { FormattingOff = true; - } else if (CommentText == "// clang-format on") { + } else if (isClangFormatOn(CommentText)) { FormattingOff = false; // Special case: consider a trailing "clang-format on" line to be part // of the module reference, so that it gets moved around together with diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 1d71bc909e8c..e61fb5f3e020 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -22620,6 +22620,28 @@ TEST_F(FormatTest, DisableRegions) { "/* clang-format off */\n" "/* long long long long long long line */\n", getLLVMStyleWithColumns(20))); + + verifyFormat("int *i;\n" + "// clang-format off:\n" + "int* j;\n" + "// clang-format on: 1\n" + "int *k;", + "int* i;\n" + "// clang-format off:\n" + "int* j;\n" + "// clang-format on: 1\n" + "int* k;"); + + verifyFormat("int *i;\n" + "// clang-format off:0\n" + "int* j;\n" + "// clang-format only\n" + "int* k;", + "int* i;\n" + "// clang-format off:0\n" + "int* j;\n" + "// clang-format only\n" + "int* k;"); } TEST_F(FormatTest, DoNotCrashOnInvalidInput) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits