[clang-tools-extra] [clang-tidy] Enhance modernize-use-starts-ends-with to handle substr patterns (PR #116033)

Nicolas van Kempen via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 18 08:18:44 PST 2024


================
@@ -183,40 +209,44 @@ void UseStartsEndsWithCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *EndsWithFunction =
       Result.Nodes.getNodeAs<CXXMethodDecl>("ends_with_fun");
   assert(bool(StartsWithFunction) != bool(EndsWithFunction));
+
   const CXXMethodDecl *ReplacementFunction =
       StartsWithFunction ? StartsWithFunction : EndsWithFunction;
 
   if (ComparisonExpr->getBeginLoc().isMacroID())
     return;
 
-  const bool Neg = ComparisonExpr->getOpcode() == BO_NE;
+  bool Neg = isNegativeComparison(ComparisonExpr);
 
-  auto Diagnostic =
-      diag(FindExpr->getExprLoc(), "use %0 instead of %1() %select{==|!=}2 0")
-      << ReplacementFunction->getName() << FindFun->getName() << Neg;
+  // Retrieve the source text of the search expression.
+  const auto SearchExprText = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(SearchExpr->getSourceRange()),
+      *Result.SourceManager, Result.Context->getLangOpts());
 
-  // Remove possible arguments after search expression and ' [!=]= .+' suffix.
-  Diagnostic << FixItHint::CreateReplacement(
-      CharSourceRange::getTokenRange(
-          Lexer::getLocForEndOfToken(SearchExpr->getEndLoc(), 0,
-                                     *Result.SourceManager, getLangOpts()),
-          ComparisonExpr->getEndLoc()),
-      ")");
+  auto Diag = diag(FindExpr->getExprLoc(),
+                   FindFun->getName() == "substr"
+                       ? "use %0 instead of %1() %select{==|!=}2"
+                       : "use %0 instead of %1() %select{==|!=}2 0")
+              << ReplacementFunction->getName() << FindFun->getName() << Neg;
 
-  // Remove possible '.+ [!=]= ' prefix.
-  Diagnostic << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+  // Remove everything before the function call.
+  Diag << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
       ComparisonExpr->getBeginLoc(), FindExpr->getBeginLoc()));
 
-  // Replace method name by '(starts|ends)_with'.
-  // Remove possible arguments before search expression.
-  Diagnostic << FixItHint::CreateReplacement(
-      CharSourceRange::getCharRange(FindExpr->getExprLoc(),
-                                    SearchExpr->getBeginLoc()),
-      (ReplacementFunction->getName() + "(").str());
+  // Rename the function to `starts_with` or `ends_with`.
+  Diag << FixItHint::CreateReplacement(FindExpr->getExprLoc(),
+                                       ReplacementFunction->getName());
+
+  // Replace arguments and everything after the function call.
+  Diag << FixItHint::CreateReplacement(
+      CharSourceRange::getTokenRange(FindExpr->getArg(0)->getBeginLoc(),
+                                     ComparisonExpr->getEndLoc()),
+      (SearchExprText + ")").str());
 
-  // Add possible negation '!'.
-  if (Neg)
-    Diagnostic << FixItHint::CreateInsertion(FindExpr->getBeginLoc(), "!");
+  // Add negation if necessary.
+  if (Neg) {
+    Diag << FixItHint::CreateInsertion(FindExpr->getBeginLoc(), "!");
+  }
----------------
nicovank wrote:

```suggestion
  if (Neg)
    Diag << FixItHint::CreateInsertion(FindExpr->getBeginLoc(), "!");
```

https://github.com/llvm/llvm-project/pull/116033


More information about the cfe-commits mailing list