[clang-tools-extra] clangd cleanupAroundReplacements just as clang-tidy does (PR #118569)

Richard Li via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 3 16:47:34 PST 2024


https://github.com/chomosuke created https://github.com/llvm/llvm-project/pull/118569

None

>From d2257eb43bbd9ce2dfd8a13123c2048e1cf8b439 Mon Sep 17 00:00:00 2001
From: chomosuke <a13323600 at gmail.com>
Date: Wed, 4 Dec 2024 00:07:31 +0000
Subject: [PATCH] clangd cleanupAroundReplacements just as clang-tidy does

---
 clang-tools-extra/clangd/Diagnostics.cpp | 48 +++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp
index a59d1e7ac84096..af8d0d534af689 100644
--- a/clang-tools-extra/clangd/Diagnostics.cpp
+++ b/clang-tools-extra/clangd/Diagnostics.cpp
@@ -19,6 +19,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
+#include "clang/Format/Format.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/Token.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -741,7 +742,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
       return false;
     // Copy as we may modify the ranges.
     auto FixIts = Info.getFixItHints().vec();
-    llvm::SmallVector<TextEdit, 1> Edits;
+    auto Replacements = std::make_optional<tooling::Replacements>();
     for (auto &FixIt : FixIts) {
       // Allow fixits within a single macro-arg expansion to be applied.
       // This can be incorrect if the argument is expanded multiple times in
@@ -761,7 +762,50 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
         return false;
       if (!isInsideMainFile(FixIt.RemoveRange.getBegin(), SM))
         return false;
-      Edits.push_back(toTextEdit(FixIt, SM, *LangOpts));
+
+      auto R = tooling::Replacement(SM, FixIt.RemoveRange, FixIt.CodeToInsert,
+                                    *LangOpts);
+      auto Err = Replacements->add(R);
+      if (Err) {
+        // FIXME: Remove duplicated code as in ClangTidy.cpp
+        unsigned NewOffset =
+            Replacements->getShiftedCodePosition(R.getOffset());
+        unsigned NewLength = Replacements->getShiftedCodePosition(
+                                 R.getOffset() + R.getLength()) -
+                             NewOffset;
+        if (NewLength == R.getLength()) {
+          llvm::consumeError(std::move(Err));
+          R = tooling::Replacement(R.getFilePath(), NewOffset, NewLength,
+                                   R.getReplacementText());
+          Replacements = Replacements->merge(tooling::Replacements(R));
+        } else {
+          log("Skipping formatting the replacement due to conflict: {0}",
+               llvm::toString(std::move(Err)));
+          Replacements = std::nullopt;
+          break;
+        }
+      }
+    }
+
+    llvm::SmallVector<TextEdit, 1> Edits;
+
+    if (Replacements) {
+      StringRef Code = SM.getBufferData(SM.getMainFileID());
+      auto Repl = format::cleanupAroundReplacements(Code, *Replacements,
+                                                    format::getNoStyle());
+      if (!Repl) {
+        log("Skipping formatting the replacement due to conflict: {0}",
+             llvm::toString(std::move(Repl.takeError())));
+        Replacements = std::nullopt;
+      } else {
+        auto Es = replacementsToEdits(Code, *Repl);
+        Edits.append(Es.begin(), Es.end());
+      }
+    }
+    if (!Replacements) {
+      for (auto &FixIt : FixIts) {
+        Edits.push_back(toTextEdit(FixIt, SM, *LangOpts));
+      }
     }
 
     llvm::SmallString<64> Message;



More information about the cfe-commits mailing list