Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
| clang/lib/Format/Format.cpp | ||
|---|---|---|
| 3901 | Should the space be required? What about // clang-format off: reasoning or similar? Also, should this be documented? | |
| clang/lib/Format/Format.cpp | ||
|---|---|---|
| 3901 |
+1 | |
| clang/lib/Format/Format.cpp | ||
|---|---|---|
| 3893 | Here's my attempt at something flexible: ////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementation detail, hide in a namespace and/or take out of the header
bool isClangFormatMarked(StringRef Comment, StringRef Mark) {
// Quick heuristics: minimum length and starts with a slash (comment)
// Shortest tag: "//clang-format on", 17 characters
static constexpr StringLiteral clangFormatStr("clang-format ");
if (Comment.size() < clangFormatStr.size() + 4 || Comment[0] != '/')
return false;
// check if it's a comment starting with "//" or "/*"
bool CloseNeeded = false;
if (Comment[1] == '*')
CloseNeeded = true;
else if (Comment[1] != '/')
return false;
// Remove the comment start and all following whitespace
Comment = Comment.substr(2).ltrim();
// Check for the actual command, a piece at a time
if (!Comment.consume_front(clangFormatStr) || !Comment.consume_front(Mark))
return false;
// Are we there yet?
if (!CloseNeeded && Comment.empty() ||
CloseNeeded && Comment.starts_with("*/"))
return true;
// For a trailer, restrict the next character
// (currently spaces and tabs, but can include a colon, etc.)
static constexpr StringLiteral Separator(" \t");
if (!Separator.contains(Comment[0]))
return false;
// Verify comment is properly terminated
if (!CloseNeeded || Comment.contains("*/"))
return true;
return false; // Everything else
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool isClangFormatOn(StringRef Comment) {
return isClangFormatMarked(Comment, "on");
}
bool isClangFormatOff(StringRef Comment) {
return isClangFormatMarked(Comment, "off");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
EXPECT_TRUE(isClangFormatOn("//clang-format on"));
EXPECT_TRUE(isClangFormatOn("// clang-format on"));
EXPECT_TRUE(isClangFormatOn("//clang-format on "));
EXPECT_TRUE(isClangFormatOn("//clang-format on and off"));
EXPECT_TRUE(isClangFormatOn("/*clang-format on*/"));
EXPECT_TRUE(isClangFormatOn("/* clang-format on*/"));
EXPECT_TRUE(isClangFormatOn("/*clang-format on */"));
EXPECT_TRUE(isClangFormatOn("/*clang-format on*/int i{0};"));
EXPECT_FALSE(isClangFormatOn("//clang-format on"));
EXPECT_FALSE(isClangFormatOn("//clang-format o"));
EXPECT_FALSE(isClangFormatOn("// clang-format o"));
EXPECT_FALSE(isClangFormatOn("//clang-format ontario"));
EXPECT_FALSE(isClangFormatOn("//clang-format off"));
EXPECT_FALSE(isClangFormatOn("/*clang-format onwards*/"));
//////////////////////////////////////////////////////////////////////////////////////////////////// | |
| clang/lib/Format/Format.cpp | ||
|---|---|---|
| 3893 | Sorry about the "done". My misunderstanding | |
| clang/lib/Format/Format.cpp | ||
|---|---|---|
| 3893 |
Thanks! If we didn't have to worry about regressions, we might want to do something like what you suggested above. | |
| 3901 |
On second thought, we should make it more restrictive to avoid regressions. How about requiring a colon, i.e. // clang-format off: (but not // clang-format off :)?
Yep. | |
Only allows : as the first character after // clang-format on or // clang-format off.
| clang/lib/Format/Format.cpp | ||
|---|---|---|
| 3901 |
That's fine by me. But why not also /**/? | |
| clang/lib/Format/Format.cpp | ||
|---|---|---|
| 3901 |
If it weren't for the fact that the code which checks for clang-format on/off exists in several places, I wouldn't want this feature added. IMO there's no need to allow /* clang-format off: */ if we got // clang-format: and being more restrictive results in a lower risk of regression. | |
| clang/lib/Format/Format.cpp | ||
|---|---|---|
| 3893 | Isn't it what extensive test coverage is for? | |
| clang/lib/Format/Format.cpp | ||
|---|---|---|
| 3893 | I meant the regression of behavior. | |
Here's my attempt at something flexible:
Disclaimer: this is my first time looking at the LLVM codebase, so don't expect production quality.
//////////////////////////////////////////////////////////////////////////////////////////////////// // Implementation detail, hide in a namespace and/or take out of the header bool isClangFormatMarked(StringRef Comment, StringRef Mark) { // Quick heuristics: minimum length and starts with a slash (comment) // Shortest tag: "//clang-format on", 17 characters static constexpr StringLiteral clangFormatStr("clang-format "); if (Comment.size() < clangFormatStr.size() + 4 || Comment[0] != '/') return false; // check if it's a comment starting with "//" or "/*" bool CloseNeeded = false; if (Comment[1] == '*') CloseNeeded = true; else if (Comment[1] != '/') return false; // Remove the comment start and all following whitespace Comment = Comment.substr(2).ltrim(); // Check for the actual command, a piece at a time if (!Comment.consume_front(clangFormatStr) || !Comment.consume_front(Mark)) return false; // Are we there yet? if (!CloseNeeded && Comment.empty() || CloseNeeded && Comment.starts_with("*/")) return true; // For a trailer, restrict the next character // (currently spaces and tabs, but can include a colon, etc.) static constexpr StringLiteral Separator(" \t"); if (!Separator.contains(Comment[0])) return false; // Verify comment is properly terminated if (!CloseNeeded || Comment.contains("*/")) return true; return false; // Everything else } //////////////////////////////////////////////////////////////////////////////////////////////////// bool isClangFormatOn(StringRef Comment) { return isClangFormatMarked(Comment, "on"); } bool isClangFormatOff(StringRef Comment) { return isClangFormatMarked(Comment, "off"); } //////////////////////////////////////////////////////////////////////////////////////////////////// EXPECT_TRUE(isClangFormatOn("//clang-format on")); EXPECT_TRUE(isClangFormatOn("// clang-format on")); EXPECT_TRUE(isClangFormatOn("//clang-format on ")); EXPECT_TRUE(isClangFormatOn("//clang-format on and off")); EXPECT_TRUE(isClangFormatOn("/*clang-format on*/")); EXPECT_TRUE(isClangFormatOn("/* clang-format on*/")); EXPECT_TRUE(isClangFormatOn("/*clang-format on */")); EXPECT_TRUE(isClangFormatOn("/*clang-format on*/int i{0};")); EXPECT_FALSE(isClangFormatOn("//clang-format on")); EXPECT_FALSE(isClangFormatOn("//clang-format o")); EXPECT_FALSE(isClangFormatOn("// clang-format o")); EXPECT_FALSE(isClangFormatOn("//clang-format ontario")); EXPECT_FALSE(isClangFormatOn("//clang-format off")); EXPECT_FALSE(isClangFormatOn("/*clang-format onwards*/")); ////////////////////////////////////////////////////////////////////////////////////////////////////