Skip to content

Commit 0dfe661

Browse files
committed
further modifications
1 parent 7e5439d commit 0dfe661

File tree

4 files changed

+118
-56
lines changed

4 files changed

+118
-56
lines changed

clang-tools-extra/clang-tidy/readability/UseCppStyleCommentsCheck.cpp

Lines changed: 95 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,56 +10,88 @@
1010
#include "clang/ASTMatchers/ASTMatchFinder.h"
1111
#include "clang/Lex/Lexer.h"
1212
#include "clang/Lex/Preprocessor.h"
13-
#include <sstream>
13+
#include <optional>
1414

1515
using namespace clang::ast_matchers;
1616

1717
namespace clang::tidy::readability {
1818
class UseCppStyleCommentsCheck::CStyleCommentHandler : public CommentHandler {
1919
public:
20-
CStyleCommentHandler(UseCppStyleCommentsCheck &Check, bool ExcludeDoxygen)
20+
CStyleCommentHandler(UseCppStyleCommentsCheck &Check, bool ExcludeDoxygen,
21+
StringRef ExcludedComments)
2122
: Check(Check), ExcludeDoxygen(ExcludeDoxygen),
23+
ExcludedComments(ExcludedComments),
24+
ExcludedCommentMatch(ExcludedComments),
2225
CStyleCommentMatch(
2326
"^[ \t]*/\\*+[ \t\r\n]*(.*[ \t\r\n]*)*[ \t\r\n]*\\*+/[ \t\r\n]*$") {
2427
}
2528

26-
void setExcludeDoxygen(bool Exclude) { ExcludeDoxygen = Exclude; }
29+
StringRef getExcludedCommentsRegex() const { return ExcludedComments; }
2730

2831
bool isExcludeDoxygen() const { return ExcludeDoxygen; }
2932

30-
std::string convertToCppStyleComment(const SourceManager &SM,
31-
const SourceRange &Range) {
32-
const StringRef CommentText = Lexer::getSourceText(
33+
void convertToCppStyleCommentFixes(const SourceManager &SM,
34+
const SourceRange &Range,
35+
SmallVectorImpl<FixItHint> &FixIts) {
36+
StringRef CommentText = Lexer::getSourceText(
3337
CharSourceRange::getTokenRange(Range), SM, LangOptions());
3438

35-
std::string InnerText = CommentText.str();
36-
InnerText.erase(0, 2);
37-
InnerText.erase(InnerText.size() - 2, 2);
38-
39-
std::string Result;
40-
std::istringstream Stream(InnerText);
41-
std::string Line;
42-
43-
if (std::getline(Stream, Line)) {
44-
const size_t StartPos = Line.find_first_not_of(" \t");
45-
if (StartPos != std::string::npos) {
46-
Line = Line.substr(StartPos);
39+
CommentText = CommentText.drop_front(2).drop_back(2);
40+
const SourceLocation StartLoc = Range.getBegin();
41+
const FileID FID = SM.getFileID(StartLoc);
42+
unsigned LineNo = SM.getSpellingLineNumber(StartLoc);
43+
const unsigned StartCol = SM.getSpellingColumnNumber(StartLoc);
44+
if (!CommentText.empty()) {
45+
const size_t NewlinePos = CommentText.find('\n');
46+
47+
const StringRef Line = (NewlinePos == StringRef::npos)
48+
? CommentText
49+
: CommentText.substr(0, NewlinePos);
50+
51+
const SourceLocation LineStart =
52+
SM.translateLineCol(FID, LineNo, StartCol);
53+
const SourceLocation LineEnd = SM.translateLineCol(
54+
FID, LineNo, std::numeric_limits<unsigned>::max());
55+
56+
FixIts.push_back(FixItHint::CreateReplacement(
57+
CharSourceRange::getCharRange(LineStart, LineEnd),
58+
"//" + Line.str()));
59+
60+
if (NewlinePos != StringRef::npos) {
61+
CommentText = CommentText.substr(NewlinePos + 1);
62+
LineNo++;
4763
} else {
48-
Line.clear();
64+
CommentText = "";
4965
}
50-
Result += "// " + Line;
5166
}
52-
53-
while (std::getline(Stream, Line)) {
54-
const size_t StartPos = Line.find_first_not_of(" \t");
55-
if (StartPos != std::string::npos) {
56-
Line = Line.substr(StartPos);
67+
while (!CommentText.empty()) {
68+
const size_t NewlinePos = CommentText.find('\n');
69+
70+
StringRef Line = (NewlinePos == StringRef::npos)
71+
? CommentText
72+
: CommentText.substr(0, NewlinePos);
73+
74+
const SourceLocation LineStart = SM.translateLineCol(FID, LineNo, 1);
75+
const SourceLocation LineEnd = SM.translateLineCol(
76+
FID, LineNo, std::numeric_limits<unsigned>::max());
77+
78+
if (Line.substr(0, 2) == " ") {
79+
Line = Line.drop_front(2);
80+
FixIts.push_back(FixItHint::CreateReplacement(
81+
CharSourceRange::getCharRange(LineStart, LineEnd),
82+
"//" + Line.str()));
5783
} else {
58-
Line.clear();
84+
FixIts.push_back(FixItHint::CreateReplacement(
85+
CharSourceRange::getCharRange(LineStart, LineEnd),
86+
"//" + Line.str()));
87+
}
88+
89+
if (NewlinePos == StringRef::npos) {
90+
break;
5991
}
60-
Result += "\n// " + Line;
92+
CommentText = CommentText.substr(NewlinePos + 1);
93+
LineNo++;
6194
}
62-
return Result;
6395
}
6496

6597
bool isDoxygenStyleComment(const StringRef &Text) {
@@ -70,23 +102,21 @@ class UseCppStyleCommentsCheck::CStyleCommentHandler : public CommentHandler {
70102
Trimmed.drop_front(2).starts_with("*"));
71103
}
72104

73-
bool CheckForTextAfterComment(Preprocessor &PP, SourceRange Range) {
105+
bool CheckForCodeAfterComment(Preprocessor &PP, SourceRange Range) {
74106
const SourceManager &SM = PP.getSourceManager();
75-
const SourceLocation CommentEnd = Range.getEnd();
76-
77-
unsigned EndLine = SM.getSpellingLineNumber(CommentEnd);
78-
unsigned EndCol = SM.getSpellingColumnNumber(CommentEnd);
79-
80-
const SourceLocation LineBegin =
81-
SM.translateLineCol(SM.getFileID(CommentEnd), EndLine, EndCol);
82-
const SourceLocation LineEnd =
83-
SM.translateLineCol(SM.getFileID(CommentEnd), EndLine,
84-
std::numeric_limits<unsigned>::max());
85-
const StringRef AfterComment =
86-
Lexer::getSourceText(CharSourceRange::getCharRange(LineBegin, LineEnd),
87-
SM, PP.getLangOpts());
88-
89-
return !AfterComment.trim().empty();
107+
const SourceLocation CommentStart = Range.getBegin(),
108+
CommentEnd = Range.getEnd();
109+
const std::optional<Token> NextTok =
110+
Lexer::findNextToken(CommentStart, SM, PP.getLangOpts());
111+
if (!NextTok.has_value()) {
112+
return false;
113+
}
114+
const std::string tokenSpelling =
115+
Lexer::getSpelling(*NextTok, SM, PP.getLangOpts());
116+
const unsigned lineNo = SM.getSpellingLineNumber(CommentEnd);
117+
const SourceLocation loc = NextTok->getLocation();
118+
const unsigned tokenLine = SM.getSpellingLineNumber(loc);
119+
return lineNo == tokenLine;
90120
}
91121

92122
bool HandleComment(Preprocessor &PP, SourceRange Range) override {
@@ -99,6 +129,12 @@ class UseCppStyleCommentsCheck::CStyleCommentHandler : public CommentHandler {
99129
const StringRef Text = Lexer::getSourceText(
100130
CharSourceRange::getCharRange(Range), SM, PP.getLangOpts());
101131

132+
if (!ExcludedCommentMatch.isValid()) {
133+
llvm::errs() << "Warning: Invalid regex pattern:" << ExcludedComments
134+
<< ":for ExcludedComments\n";
135+
} else if (ExcludedCommentMatch.match(Text)) {
136+
return false;
137+
}
102138
if (ExcludeDoxygen && isDoxygenStyleComment(Text)) {
103139
return false;
104140
}
@@ -108,30 +144,38 @@ class UseCppStyleCommentsCheck::CStyleCommentHandler : public CommentHandler {
108144
return false;
109145
}
110146

111-
if (CheckForTextAfterComment(PP, Range)) {
147+
if (CheckForCodeAfterComment(PP, Range)) {
112148
return false;
113149
}
114150

115-
Check.diag(
151+
SmallVector<FixItHint, 4> FixIts;
152+
convertToCppStyleCommentFixes(SM, Range, FixIts);
153+
154+
auto D = Check.diag(
116155
Range.getBegin(),
117-
"use C++ style comments '//' instead of C style comments '/*...*/'")
118-
<< clang::FixItHint::CreateReplacement(
119-
Range, convertToCppStyleComment(SM, Range));
156+
"use C++ style comments '//' instead of C style comments '/*...*/'");
157+
158+
for (const auto &Fix : FixIts) {
159+
D << Fix;
160+
}
120161

121162
return false;
122163
}
123164

124165
private:
125166
UseCppStyleCommentsCheck &Check;
126167
bool ExcludeDoxygen;
168+
StringRef ExcludedComments;
169+
llvm::Regex ExcludedCommentMatch;
127170
llvm::Regex CStyleCommentMatch;
128171
};
129172

130173
UseCppStyleCommentsCheck::UseCppStyleCommentsCheck(StringRef Name,
131174
ClangTidyContext *Context)
132175
: ClangTidyCheck(Name, Context),
133176
Handler(std::make_unique<CStyleCommentHandler>(
134-
*this, Options.get("ExcludeDoxygenStyleComments", false))) {}
177+
*this, Options.get("ExcludeDoxygenStyleComments", false),
178+
Options.get("ExcludedComments", "^$"))) {}
135179

136180
void UseCppStyleCommentsCheck::registerPPCallbacks(
137181
const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
@@ -143,6 +187,7 @@ void UseCppStyleCommentsCheck::check(const MatchFinder::MatchResult &Result) {}
143187
void UseCppStyleCommentsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
144188
Options.store(Opts, "ExcludeDoxygenStyleComments",
145189
Handler->isExcludeDoxygen());
190+
Options.store(Opts, "ExcludedComments", Handler->getExcludedCommentsRegex());
146191
}
147192

148193
UseCppStyleCommentsCheck::~UseCppStyleCommentsCheck() = default;

clang-tools-extra/clang-tidy/readability/UseCppStyleCommentsCheck.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
namespace clang::tidy::readability {
1616
/// Detects C Style comments and suggests to use C++ style comments instead.
1717
///
18-
/// Optionally excludes Doxygen-style comments.
19-
///
2018
/// For the user-facing documentation see:
2119
/// http://clang.llvm.org/extra/clang-tidy/checks/readability/use-cpp-style-comments.html
2220
class UseCppStyleCommentsCheck : public ClangTidyCheck {
@@ -41,6 +39,7 @@ class UseCppStyleCommentsCheck : public ClangTidyCheck {
4139
std::unique_ptr<CStyleCommentHandler> Handler;
4240
const bool ExcludeDoxygenStyleComments =
4341
Options.get("ExcludeDoxygenStyleComments", false);
42+
const StringRef ExcludedComments = Options.get("ExcludedComments", "^$");
4443
};
4544
} // namespace clang::tidy::readability
4645

clang-tools-extra/docs/clang-tidy/checks/readability/use-cpp-style-comments.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,9 @@ Options
4949

5050
A boolean option that determines whether Doxygen-style comments should be excluded.
5151
By default, this option is set to ``false``.
52+
53+
.. option:: ExcludedComments
54+
55+
A regex pattern that allows specifying certain comments to exclude from transformation.
56+
By default, this option is set to "^$", which means no comments are excluded.
57+
You can provide a custom regex to exclude specific comments based on your needs.

clang-tools-extra/test/clang-tidy/checkers/readability/use-cpp-style-comments.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ int complexCalculation = calculateSomething(); /* Result of complex calculation
3232

3333
// Nested comments and edge cases
3434
void edgeCaseFunction() {
35-
int x = 10 /* First value */ + 20 /* Second value */; // Inline comments should not transform
35+
int x = 10 /* First value */ + 20 /* Second value */; // Inline comments should not transform
3636

3737
/* Comment with special characters !@#$%^&*()_+ */
3838
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use C++ style comments '//' instead of C style comments '/*...*/' [readability-use-cpp-style-comments]
@@ -44,7 +44,7 @@ void edgeCaseFunction() {
4444
and should preserve indentation when converted */
4545
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use C++ style comments '//' instead of C style comments '/*...*/' [readability-use-cpp-style-comments]
4646
// CHECK-FIXES: // This comment is indented
47-
// CHECK-FIXES: // and should preserve indentation when converted
47+
// CHECK-FIXES: // and should preserve indentation when converted
4848

4949
// Complex function with mixed comment types
5050
void complexFunction() {
@@ -60,9 +60,21 @@ void complexFunction() {
6060
/* aaa
6161
bbbb
6262
ccc */ int z = 1;
63-
// There is a text after the comment ends so it should be ignored.
63+
// There is a token after the comment ends so it should be ignored.
6464

6565
int y = 10;/* aaa
6666
bbbb
6767
ccc */ int z1 = 1;
68-
// There is a text after the comment ends so it should be ignored.
68+
// There is a token after the comment ends so it should be ignored.
69+
70+
/* aaa
71+
a // abc
72+
bbb */
73+
// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: use C++ style comments '//' instead of C style comments '/*...*/' [readability-use-cpp-style-comments]
74+
// CHECK-FIXES: // aaa
75+
// CHECK-FIXES: //a // abc
76+
// CHECK-FIXES: // bbb
77+
78+
int k1 = 49; /* aa //bbbb aa *///
79+
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use C++ style comments '//' instead of C style comments '/*...*/' [readability-use-cpp-style-comments]
80+
// CHECK-FIXES: // aa //bbbb aa

0 commit comments

Comments
 (0)