-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[clang-tidy][NFC] refactor modernize-raw-string-literal fix hint #122909
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
Merged
HerrCai0907
merged 1 commit into
main
from
users/ccc01-14-_clang-tidy_nfc_refactor_modernize-raw-string-literal_fix_hint
Jan 17, 2025
Merged
[clang-tidy][NFC] refactor modernize-raw-string-literal fix hint #122909
HerrCai0907
merged 1 commit into
main
from
users/ccc01-14-_clang-tidy_nfc_refactor_modernize-raw-string-literal_fix_hint
Jan 17, 2025
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Contributor
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Member
|
@llvm/pr-subscribers-clang-tools-extra Author: Congcong Cai (HerrCai0907) ChangesFull diff: https://github.com/llvm/llvm-project/pull/122909.diff 2 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp b/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp
index bd9830278facb7..1618b5be7699d9 100644
--- a/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp
@@ -9,8 +9,11 @@
#include "RawStringLiteralCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/StringRef.h"
+#include <optional>
using namespace clang::ast_matchers;
@@ -67,20 +70,6 @@ bool containsDelimiter(StringRef Bytes, const std::string &Delimiter) {
: (")" + Delimiter + R"(")")) != StringRef::npos;
}
-std::string asRawStringLiteral(const StringLiteral *Literal,
- const std::string &DelimiterStem) {
- const StringRef Bytes = Literal->getBytes();
- std::string Delimiter;
- for (int I = 0; containsDelimiter(Bytes, Delimiter); ++I) {
- Delimiter = (I == 0) ? DelimiterStem : DelimiterStem + std::to_string(I);
- }
-
- if (Delimiter.empty())
- return (R"(R"()" + Bytes + R"lit()")lit").str();
-
- return (R"(R")" + Delimiter + "(" + Bytes + ")" + Delimiter + R"(")").str();
-}
-
} // namespace
RawStringLiteralCheck::RawStringLiteralCheck(StringRef Name,
@@ -120,43 +109,73 @@ void RawStringLiteralCheck::registerMatchers(MatchFinder *Finder) {
stringLiteral(unless(hasParent(predefinedExpr()))).bind("lit"), this);
}
-void RawStringLiteralCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *Literal = Result.Nodes.getNodeAs<StringLiteral>("lit");
- if (Literal->getBeginLoc().isMacroID())
- return;
-
- if (containsEscapedCharacters(Result, Literal, DisallowedChars)) {
- std::string Replacement = asRawStringLiteral(Literal, DelimiterStem);
- if (ReplaceShorterLiterals ||
- Replacement.length() <=
- Lexer::MeasureTokenLength(Literal->getBeginLoc(),
- *Result.SourceManager, getLangOpts()))
- replaceWithRawStringLiteral(Result, Literal, Replacement);
- }
-}
-
-void RawStringLiteralCheck::replaceWithRawStringLiteral(
- const MatchFinder::MatchResult &Result, const StringLiteral *Literal,
- std::string Replacement) {
- DiagnosticBuilder Builder =
- diag(Literal->getBeginLoc(),
- "escaped string literal can be written as a raw string literal");
- const SourceManager &SM = *Result.SourceManager;
+static std::optional<StringRef>
+createUserDefinedSuffix(const StringLiteral *Literal, const SourceManager &SM,
+ const LangOptions &LangOpts) {
const CharSourceRange TokenRange =
CharSourceRange::getTokenRange(Literal->getSourceRange());
Token T;
- if (Lexer::getRawToken(Literal->getBeginLoc(), T, SM, getLangOpts()))
- return;
+ if (Lexer::getRawToken(Literal->getBeginLoc(), T, SM, LangOpts))
+ return std::nullopt;
const CharSourceRange CharRange =
- Lexer::makeFileCharRange(TokenRange, SM, getLangOpts());
+ Lexer::makeFileCharRange(TokenRange, SM, LangOpts);
if (T.hasUDSuffix()) {
- StringRef Text = Lexer::getSourceText(CharRange, SM, getLangOpts());
+ StringRef Text = Lexer::getSourceText(CharRange, SM, LangOpts);
const size_t UDSuffixPos = Text.find_last_of('"');
if (UDSuffixPos == StringRef::npos)
- return;
- Replacement += Text.slice(UDSuffixPos + 1, Text.size());
+ return std::nullopt;
+ return Text.slice(UDSuffixPos + 1, Text.size());
+ }
+ return std::nullopt;
+}
+
+static std::string createRawStringLiteral(const StringLiteral *Literal,
+ const std::string &DelimiterStem,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ const StringRef Bytes = Literal->getBytes();
+ std::string Delimiter;
+ for (int I = 0; containsDelimiter(Bytes, Delimiter); ++I) {
+ Delimiter = (I == 0) ? DelimiterStem : DelimiterStem + std::to_string(I);
+ }
+
+ std::optional<StringRef> UserDefinedSuffix =
+ createUserDefinedSuffix(Literal, SM, LangOpts);
+
+ if (Delimiter.empty())
+ return (R"(R"()" + Bytes + R"lit()")lit" + UserDefinedSuffix.value_or(""))
+ .str();
+
+ return (R"(R")" + Delimiter + "(" + Bytes + ")" + Delimiter + R"(")" +
+ UserDefinedSuffix.value_or(""))
+ .str();
+}
+
+static bool compareStringLength(StringRef Replacement,
+ const StringLiteral *Literal,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ return Replacement.size() <=
+ Lexer::MeasureTokenLength(Literal->getBeginLoc(), SM, LangOpts);
+}
+
+void RawStringLiteralCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *Literal = Result.Nodes.getNodeAs<StringLiteral>("lit");
+ if (Literal->getBeginLoc().isMacroID())
+ return;
+ SourceManager const &SM = *Result.SourceManager;
+ LangOptions const &LangOpts = getLangOpts();
+ if (containsEscapedCharacters(Result, Literal, DisallowedChars)) {
+ std::string Replacement =
+ createRawStringLiteral(Literal, DelimiterStem, SM, LangOpts);
+ if (ReplaceShorterLiterals ||
+ compareStringLength(Replacement, Literal, SM, LangOpts)) {
+ diag(Literal->getBeginLoc(),
+ "escaped string literal can be written as a raw string literal")
+ << FixItHint::CreateReplacement(Literal->getSourceRange(),
+ Replacement);
+ }
}
- Builder << FixItHint::CreateReplacement(CharRange, Replacement);
}
} // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h b/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h
index 6898e0624d1eb8..879255550dd5b6 100644
--- a/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h
@@ -33,10 +33,6 @@ class RawStringLiteralCheck : public ClangTidyCheck {
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
- void replaceWithRawStringLiteral(
- const ast_matchers::MatchFinder::MatchResult &Result,
- const StringLiteral *Literal, std::string Replacement);
-
std::string DelimiterStem;
CharsBitSet DisallowedChars;
const bool ReplaceShorterLiterals;
|
Member
|
@llvm/pr-subscribers-clang-tidy Author: Congcong Cai (HerrCai0907) ChangesFull diff: https://github.com/llvm/llvm-project/pull/122909.diff 2 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp b/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp
index bd9830278facb7..1618b5be7699d9 100644
--- a/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp
@@ -9,8 +9,11 @@
#include "RawStringLiteralCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/StringRef.h"
+#include <optional>
using namespace clang::ast_matchers;
@@ -67,20 +70,6 @@ bool containsDelimiter(StringRef Bytes, const std::string &Delimiter) {
: (")" + Delimiter + R"(")")) != StringRef::npos;
}
-std::string asRawStringLiteral(const StringLiteral *Literal,
- const std::string &DelimiterStem) {
- const StringRef Bytes = Literal->getBytes();
- std::string Delimiter;
- for (int I = 0; containsDelimiter(Bytes, Delimiter); ++I) {
- Delimiter = (I == 0) ? DelimiterStem : DelimiterStem + std::to_string(I);
- }
-
- if (Delimiter.empty())
- return (R"(R"()" + Bytes + R"lit()")lit").str();
-
- return (R"(R")" + Delimiter + "(" + Bytes + ")" + Delimiter + R"(")").str();
-}
-
} // namespace
RawStringLiteralCheck::RawStringLiteralCheck(StringRef Name,
@@ -120,43 +109,73 @@ void RawStringLiteralCheck::registerMatchers(MatchFinder *Finder) {
stringLiteral(unless(hasParent(predefinedExpr()))).bind("lit"), this);
}
-void RawStringLiteralCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *Literal = Result.Nodes.getNodeAs<StringLiteral>("lit");
- if (Literal->getBeginLoc().isMacroID())
- return;
-
- if (containsEscapedCharacters(Result, Literal, DisallowedChars)) {
- std::string Replacement = asRawStringLiteral(Literal, DelimiterStem);
- if (ReplaceShorterLiterals ||
- Replacement.length() <=
- Lexer::MeasureTokenLength(Literal->getBeginLoc(),
- *Result.SourceManager, getLangOpts()))
- replaceWithRawStringLiteral(Result, Literal, Replacement);
- }
-}
-
-void RawStringLiteralCheck::replaceWithRawStringLiteral(
- const MatchFinder::MatchResult &Result, const StringLiteral *Literal,
- std::string Replacement) {
- DiagnosticBuilder Builder =
- diag(Literal->getBeginLoc(),
- "escaped string literal can be written as a raw string literal");
- const SourceManager &SM = *Result.SourceManager;
+static std::optional<StringRef>
+createUserDefinedSuffix(const StringLiteral *Literal, const SourceManager &SM,
+ const LangOptions &LangOpts) {
const CharSourceRange TokenRange =
CharSourceRange::getTokenRange(Literal->getSourceRange());
Token T;
- if (Lexer::getRawToken(Literal->getBeginLoc(), T, SM, getLangOpts()))
- return;
+ if (Lexer::getRawToken(Literal->getBeginLoc(), T, SM, LangOpts))
+ return std::nullopt;
const CharSourceRange CharRange =
- Lexer::makeFileCharRange(TokenRange, SM, getLangOpts());
+ Lexer::makeFileCharRange(TokenRange, SM, LangOpts);
if (T.hasUDSuffix()) {
- StringRef Text = Lexer::getSourceText(CharRange, SM, getLangOpts());
+ StringRef Text = Lexer::getSourceText(CharRange, SM, LangOpts);
const size_t UDSuffixPos = Text.find_last_of('"');
if (UDSuffixPos == StringRef::npos)
- return;
- Replacement += Text.slice(UDSuffixPos + 1, Text.size());
+ return std::nullopt;
+ return Text.slice(UDSuffixPos + 1, Text.size());
+ }
+ return std::nullopt;
+}
+
+static std::string createRawStringLiteral(const StringLiteral *Literal,
+ const std::string &DelimiterStem,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ const StringRef Bytes = Literal->getBytes();
+ std::string Delimiter;
+ for (int I = 0; containsDelimiter(Bytes, Delimiter); ++I) {
+ Delimiter = (I == 0) ? DelimiterStem : DelimiterStem + std::to_string(I);
+ }
+
+ std::optional<StringRef> UserDefinedSuffix =
+ createUserDefinedSuffix(Literal, SM, LangOpts);
+
+ if (Delimiter.empty())
+ return (R"(R"()" + Bytes + R"lit()")lit" + UserDefinedSuffix.value_or(""))
+ .str();
+
+ return (R"(R")" + Delimiter + "(" + Bytes + ")" + Delimiter + R"(")" +
+ UserDefinedSuffix.value_or(""))
+ .str();
+}
+
+static bool compareStringLength(StringRef Replacement,
+ const StringLiteral *Literal,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ return Replacement.size() <=
+ Lexer::MeasureTokenLength(Literal->getBeginLoc(), SM, LangOpts);
+}
+
+void RawStringLiteralCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *Literal = Result.Nodes.getNodeAs<StringLiteral>("lit");
+ if (Literal->getBeginLoc().isMacroID())
+ return;
+ SourceManager const &SM = *Result.SourceManager;
+ LangOptions const &LangOpts = getLangOpts();
+ if (containsEscapedCharacters(Result, Literal, DisallowedChars)) {
+ std::string Replacement =
+ createRawStringLiteral(Literal, DelimiterStem, SM, LangOpts);
+ if (ReplaceShorterLiterals ||
+ compareStringLength(Replacement, Literal, SM, LangOpts)) {
+ diag(Literal->getBeginLoc(),
+ "escaped string literal can be written as a raw string literal")
+ << FixItHint::CreateReplacement(Literal->getSourceRange(),
+ Replacement);
+ }
}
- Builder << FixItHint::CreateReplacement(CharRange, Replacement);
}
} // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h b/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h
index 6898e0624d1eb8..879255550dd5b6 100644
--- a/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h
@@ -33,10 +33,6 @@ class RawStringLiteralCheck : public ClangTidyCheck {
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
- void replaceWithRawStringLiteral(
- const ast_matchers::MatchFinder::MatchResult &Result,
- const StringLiteral *Literal, std::string Replacement);
-
std::string DelimiterStem;
CharsBitSet DisallowedChars;
const bool ReplaceShorterLiterals;
|
c413bd7 to
9e5c5eb
Compare
6cabc9d to
6cec0eb
Compare
Contributor
Author
Base automatically changed from
users/ccc01-14-_clang-tidy_fix_incorrect_auto-fix_for_the_string_contains_a_user-defined_suffix
to
main
January 17, 2025 13:41
9e5c5eb to
9d80866
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.

No description provided.