[clang] 25e2d0f - [clang-format] Support clang-format on/off line comments as prefix
Owen Pan via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 1 13:07:18 PST 2023
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) {
More information about the cfe-commits
mailing list