-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[clang-format] Option to insert spaces before the closing */
#162105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[clang-format] Option to insert spaces before the closing */
#162105
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-clang Author: Men-cotton (Men-cotton) Changes#160682 Full diff: https://github.com/llvm/llvm-project/pull/162105.diff 6 Files Affected:
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index b746df5dab264..70582b6c40980 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -6343,6 +6343,17 @@ the configuration (without a prefix: ``Auto``).
case 1 : break; case 1: break;
} }
+.. _SpaceBeforeClosingBlockComment:
+
+**SpaceBeforeClosingBlockComment** (``Boolean``) :versionbadge:`clang-format 21` :ref:`¶ <SpaceBeforeClosingBlockComment>`
+ If ``true``, a space is inserted immediately before the closing ``*/`` in
+ block comments that contain content.
+
+ .. code-block:: c++
+
+ true: false:
+ /* comment */ vs. /* comment*/
+
.. _SpaceBeforeCpp11BracedList:
**SpaceBeforeCpp11BracedList** (``Boolean``) :versionbadge:`clang-format 7` :ref:`¶ <SpaceBeforeCpp11BracedList>`
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 3df5b92654094..7136fd2c5a4f8 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4684,6 +4684,15 @@ struct FormatStyle {
/// \version 17
bool SpaceBeforeJsonColon;
+ /// If ``true``, a space is inserted immediately before the closing ``*/`` in
+ /// block comments that contain content.
+ /// \code
+ /// true: false:
+ /// /* comment */ vs. /* comment*/
+ /// \endcode
+ /// \version 21
+ bool SpaceBeforeClosingBlockComment;
+
/// Different ways to put a space before opening parentheses.
enum SpaceBeforeParensStyle : int8_t {
/// This is **deprecated** and replaced by ``Custom`` below, with all
@@ -5611,6 +5620,7 @@ struct FormatStyle {
SpaceAroundPointerQualifiers == R.SpaceAroundPointerQualifiers &&
SpaceBeforeRangeBasedForLoopColon ==
R.SpaceBeforeRangeBasedForLoopColon &&
+ SpaceBeforeClosingBlockComment == R.SpaceBeforeClosingBlockComment &&
SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets &&
SpaceInEmptyBraces == R.SpaceInEmptyBraces &&
SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 686e54128d372..06292c75f27e0 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1222,6 +1222,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("SpaceBeforeInheritanceColon",
Style.SpaceBeforeInheritanceColon);
IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon);
+ IO.mapOptional("SpaceBeforeClosingBlockComment",
+ Style.SpaceBeforeClosingBlockComment);
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);
IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
@@ -1717,6 +1719,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceBeforeCtorInitializerColon = true;
LLVMStyle.SpaceBeforeInheritanceColon = true;
LLVMStyle.SpaceBeforeJsonColon = false;
+ LLVMStyle.SpaceBeforeClosingBlockComment = false;
LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
LLVMStyle.SpaceBeforeParensOptions = {};
LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index 86a5185a92a52..b48d1b7a82026 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -18,8 +18,11 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Regex.h"
+#include <algorithm>
+
namespace clang {
namespace format {
@@ -1386,6 +1389,22 @@ FormatToken *FormatTokenLexer::getNextToken() {
StringRef UntrimmedText = FormatTok->TokenText;
FormatTok->TokenText = FormatTok->TokenText.rtrim(" \t\v\f");
TrailingWhitespace = UntrimmedText.size() - FormatTok->TokenText.size();
+ if (Style.SpaceBeforeClosingBlockComment &&
+ FormatTok->TokenText.starts_with("/*") &&
+ FormatTok->TokenText.ends_with("*/")) {
+ StringRef Body = FormatTok->TokenText.drop_front(2).drop_back(2);
+ if (!Body.empty()) {
+ const char BeforeClosing = Body.back();
+ if (!isWhitespace(static_cast<unsigned char>(BeforeClosing))) {
+ llvm::SmallString<64> Adjusted(FormatTok->TokenText);
+ Adjusted.insert(Adjusted.end() - 2, ' ');
+ char *Storage = CommentTextAllocator.Allocate<char>(Adjusted.size());
+ std::copy(Adjusted.begin(), Adjusted.end(), Storage);
+ FormatTok->TokenText = StringRef(Storage, Adjusted.size());
+ FormatTok->Tok.setLength(FormatTok->TokenText.size());
+ }
+ }
+ }
} else if (FormatTok->is(tok::raw_identifier)) {
IdentifierInfo &Info = IdentTable.get(FormatTok->TokenText);
FormatTok->Tok.setIdentifierInfo(&Info);
diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h
index 57c572af3defd..65b1199c1501c 100644
--- a/clang/lib/Format/FormatTokenLexer.h
+++ b/clang/lib/Format/FormatTokenLexer.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Allocator.h"
#include <stack>
@@ -130,6 +131,8 @@ class FormatTokenLexer {
unsigned FirstInLineIndex;
SmallVector<FormatToken *, 16> Tokens;
+ llvm::BumpPtrAllocator CommentTextAllocator;
+
llvm::SmallMapVector<IdentifierInfo *, TokenType, 8> Macros;
llvm::SmallPtrSet<IdentifierInfo *, 8> MacrosSkippedByRemoveParentheses,
diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp
index 69026bce98705..e12e17c0e12a8 100644
--- a/clang/unittests/Format/FormatTestComments.cpp
+++ b/clang/unittests/Format/FormatTestComments.cpp
@@ -332,6 +332,17 @@ TEST_F(FormatTestComments, UnderstandsSingleLineComments) {
verifyNoCrash(StringRef("/*\\\0\n/", 6));
}
+TEST_F(FormatTestComments, InsertsSpaceBeforeClosingBlockComment) {
+ FormatStyle Style = getLLVMStyle();
+ Style.SpaceBeforeClosingBlockComment = true;
+
+ verifyFormat("foo(/* comment */);", "foo(/* comment*/);", Style);
+ verifyFormat("foo(/*Logger= */nullptr);", "foo(/*Logger=*/nullptr);", Style);
+ verifyFormat("/* comment */", Style);
+ verifyFormat("/* leading */\nint x;", Style);
+ verifyFormat("/* multiline\n */", Style);
+}
+
TEST_F(FormatTestComments, KeepsParameterWithTrailingCommentsOnTheirOwnLine) {
EXPECT_EQ("SomeFunction(a,\n"
" b, // comment\n"
|
@llvm/pr-subscribers-clang-format Author: Men-cotton (Men-cotton) Changes#160682 Full diff: https://github.com/llvm/llvm-project/pull/162105.diff 6 Files Affected:
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index b746df5dab264..70582b6c40980 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -6343,6 +6343,17 @@ the configuration (without a prefix: ``Auto``).
case 1 : break; case 1: break;
} }
+.. _SpaceBeforeClosingBlockComment:
+
+**SpaceBeforeClosingBlockComment** (``Boolean``) :versionbadge:`clang-format 21` :ref:`¶ <SpaceBeforeClosingBlockComment>`
+ If ``true``, a space is inserted immediately before the closing ``*/`` in
+ block comments that contain content.
+
+ .. code-block:: c++
+
+ true: false:
+ /* comment */ vs. /* comment*/
+
.. _SpaceBeforeCpp11BracedList:
**SpaceBeforeCpp11BracedList** (``Boolean``) :versionbadge:`clang-format 7` :ref:`¶ <SpaceBeforeCpp11BracedList>`
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 3df5b92654094..7136fd2c5a4f8 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4684,6 +4684,15 @@ struct FormatStyle {
/// \version 17
bool SpaceBeforeJsonColon;
+ /// If ``true``, a space is inserted immediately before the closing ``*/`` in
+ /// block comments that contain content.
+ /// \code
+ /// true: false:
+ /// /* comment */ vs. /* comment*/
+ /// \endcode
+ /// \version 21
+ bool SpaceBeforeClosingBlockComment;
+
/// Different ways to put a space before opening parentheses.
enum SpaceBeforeParensStyle : int8_t {
/// This is **deprecated** and replaced by ``Custom`` below, with all
@@ -5611,6 +5620,7 @@ struct FormatStyle {
SpaceAroundPointerQualifiers == R.SpaceAroundPointerQualifiers &&
SpaceBeforeRangeBasedForLoopColon ==
R.SpaceBeforeRangeBasedForLoopColon &&
+ SpaceBeforeClosingBlockComment == R.SpaceBeforeClosingBlockComment &&
SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets &&
SpaceInEmptyBraces == R.SpaceInEmptyBraces &&
SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 686e54128d372..06292c75f27e0 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1222,6 +1222,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("SpaceBeforeInheritanceColon",
Style.SpaceBeforeInheritanceColon);
IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon);
+ IO.mapOptional("SpaceBeforeClosingBlockComment",
+ Style.SpaceBeforeClosingBlockComment);
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);
IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
@@ -1717,6 +1719,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceBeforeCtorInitializerColon = true;
LLVMStyle.SpaceBeforeInheritanceColon = true;
LLVMStyle.SpaceBeforeJsonColon = false;
+ LLVMStyle.SpaceBeforeClosingBlockComment = false;
LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
LLVMStyle.SpaceBeforeParensOptions = {};
LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index 86a5185a92a52..b48d1b7a82026 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -18,8 +18,11 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Regex.h"
+#include <algorithm>
+
namespace clang {
namespace format {
@@ -1386,6 +1389,22 @@ FormatToken *FormatTokenLexer::getNextToken() {
StringRef UntrimmedText = FormatTok->TokenText;
FormatTok->TokenText = FormatTok->TokenText.rtrim(" \t\v\f");
TrailingWhitespace = UntrimmedText.size() - FormatTok->TokenText.size();
+ if (Style.SpaceBeforeClosingBlockComment &&
+ FormatTok->TokenText.starts_with("/*") &&
+ FormatTok->TokenText.ends_with("*/")) {
+ StringRef Body = FormatTok->TokenText.drop_front(2).drop_back(2);
+ if (!Body.empty()) {
+ const char BeforeClosing = Body.back();
+ if (!isWhitespace(static_cast<unsigned char>(BeforeClosing))) {
+ llvm::SmallString<64> Adjusted(FormatTok->TokenText);
+ Adjusted.insert(Adjusted.end() - 2, ' ');
+ char *Storage = CommentTextAllocator.Allocate<char>(Adjusted.size());
+ std::copy(Adjusted.begin(), Adjusted.end(), Storage);
+ FormatTok->TokenText = StringRef(Storage, Adjusted.size());
+ FormatTok->Tok.setLength(FormatTok->TokenText.size());
+ }
+ }
+ }
} else if (FormatTok->is(tok::raw_identifier)) {
IdentifierInfo &Info = IdentTable.get(FormatTok->TokenText);
FormatTok->Tok.setIdentifierInfo(&Info);
diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h
index 57c572af3defd..65b1199c1501c 100644
--- a/clang/lib/Format/FormatTokenLexer.h
+++ b/clang/lib/Format/FormatTokenLexer.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Allocator.h"
#include <stack>
@@ -130,6 +131,8 @@ class FormatTokenLexer {
unsigned FirstInLineIndex;
SmallVector<FormatToken *, 16> Tokens;
+ llvm::BumpPtrAllocator CommentTextAllocator;
+
llvm::SmallMapVector<IdentifierInfo *, TokenType, 8> Macros;
llvm::SmallPtrSet<IdentifierInfo *, 8> MacrosSkippedByRemoveParentheses,
diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp
index 69026bce98705..e12e17c0e12a8 100644
--- a/clang/unittests/Format/FormatTestComments.cpp
+++ b/clang/unittests/Format/FormatTestComments.cpp
@@ -332,6 +332,17 @@ TEST_F(FormatTestComments, UnderstandsSingleLineComments) {
verifyNoCrash(StringRef("/*\\\0\n/", 6));
}
+TEST_F(FormatTestComments, InsertsSpaceBeforeClosingBlockComment) {
+ FormatStyle Style = getLLVMStyle();
+ Style.SpaceBeforeClosingBlockComment = true;
+
+ verifyFormat("foo(/* comment */);", "foo(/* comment*/);", Style);
+ verifyFormat("foo(/*Logger= */nullptr);", "foo(/*Logger=*/nullptr);", Style);
+ verifyFormat("/* comment */", Style);
+ verifyFormat("/* leading */\nint x;", Style);
+ verifyFormat("/* multiline\n */", Style);
+}
+
TEST_F(FormatTestComments, KeepsParameterWithTrailingCommentsOnTheirOwnLine) {
EXPECT_EQ("SomeFunction(a,\n"
" b, // comment\n"
|
*/
9f59655
to
ed55a3b
Compare
9b0b3cf
to
975bc0b
Compare
fe5908b
to
3cfb708
Compare
/// block comments that contain content. | ||
/// \code | ||
/// true: false: | ||
/// /* comment */ vs. /* comment*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want options to handle this differently.
foo(/*bar=*/true);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to have at least Space, NoSpace, Leave because the default of false is going to now remove spaces everywhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All options normally go through a phase boolean -> enum -> struct I think in this case we should short circuit straight to struct
struct SpaceInComments
{
AfterOpeningComment = Leave
BeforeClosingComment = Leave
AfterOpeningParamComment = Leave
BeforeCloseingParamComment = No // I think this is the current behavior
}
SpaceAroundPointerQualifiers == R.SpaceAroundPointerQualifiers && | ||
SpaceBeforeRangeBasedForLoopColon == | ||
R.SpaceBeforeRangeBasedForLoopColon && | ||
SpaceBeforeClosingBlockComment == R.SpaceBeforeClosingBlockComment && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alphabetic ordering please
Style.SpaceBeforeClosingBlockComment = true; | ||
|
||
verifyFormat("foo(/* comment */);", "foo(/* comment*/);", Style); | ||
verifyFormat("foo(/*Logger= */nullptr);", "foo(/*Logger=*/nullptr);", Style); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I want to handle this different from comments
verifyFormat("switch (n) {\n" | ||
"case 1:\n" | ||
" foo();\n" | ||
"/*FALLTHROUGH */ case 2:\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to handle "/*" while we are at it..
#160682