[llvm-branch-commits] [clang-tools-extra] [clang-tidy][NFC] refactor modernize-raw-string-literal fix hint (PR #122909)
Congcong Cai via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Jan 14 06:53:44 PST 2025
https://github.com/HerrCai0907 updated https://github.com/llvm/llvm-project/pull/122909
>From 9e5c5eb96a65d9bdec47566c9bf5ae95c57107f0 Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Tue, 14 Jan 2025 22:24:46 +0800
Subject: [PATCH] [clang-tidy][NFC] refactor modernize-raw-string-literal fix
hint
---
.../modernize/RawStringLiteralCheck.cpp | 105 +++++++++++-------
.../modernize/RawStringLiteralCheck.h | 4 -
2 files changed, 62 insertions(+), 47 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp b/clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp
index 126463ae795eb6..24674a407cb369 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()) {
- const 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;
+ const SourceManager &SM = *Result.SourceManager;
+ const LangOptions &LangOpts = getLangOpts();
+ if (containsEscapedCharacters(Result, Literal, DisallowedChars)) {
+ const 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;
More information about the llvm-branch-commits
mailing list