[clang-tools-extra] 3f3a235 - [clang-apply-replacements] Added an option to ignore insert conflict.

via cfe-commits cfe-commits at lists.llvm.org
Sun May 29 22:05:27 PDT 2022


Author: Sockke
Date: 2022-05-30T13:02:25+08:00
New Revision: 3f3a235aa2e610b5ba393228a666d55a8135ef4a

URL: https://github.com/llvm/llvm-project/commit/3f3a235aa2e610b5ba393228a666d55a8135ef4a
DIFF: https://github.com/llvm/llvm-project/commit/3f3a235aa2e610b5ba393228a666d55a8135ef4a.diff

LOG: [clang-apply-replacements] Added an option to ignore insert conflict.

If two different texts are inserted at the same offset, clang-apply-replacements prints the conflict error and discards all fixes. This patch adds support for adjusting conflict offset and keeps running to continually fix them.

https://godbolt.org/z/P938EGoxj doesn't have any fixes when I run run-clang-tidy.py to generate a YAML file with clang-tidy and fix them with clang-apply-replacements. The YAML file has two different header texts insertions at the same offset, unlike clang-tidy with '-fix', clang-apply-replacements does not adjust for this conflict.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D123924

Added: 
    clang-tools-extra/test/clang-apply-replacements/Inputs/ignore-conflict/file1.yaml
    clang-tools-extra/test/clang-apply-replacements/Inputs/ignore-conflict/ignore-conflict.cpp
    clang-tools-extra/test/clang-apply-replacements/ignore-conflict.cpp

Modified: 
    clang-tools-extra/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h
    clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
    clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
    clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
    clang/include/clang/Tooling/Refactoring/AtomicChange.h

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h b/clang-tools-extra/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h
index e37768277c5a4..b0cf7317c0ed8 100644
--- a/clang-tools-extra/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h
+++ b/clang-tools-extra/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h
@@ -87,7 +87,8 @@ std::error_code collectReplacementsFromDirectory(
 ///          \li false If there were conflicts.
 bool mergeAndDeduplicate(const TUReplacements &TUs, const TUDiagnostics &TUDs,
                          FileToChangesMap &FileChanges,
-                         clang::SourceManager &SM);
+                         clang::SourceManager &SM,
+                         bool IgnoreInsertConflict = false);
 
 /// Apply \c AtomicChange on File and rewrite it.
 ///

diff  --git a/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp b/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
index b13b83cf3f000..e25c8e2449dc8 100644
--- a/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
+++ b/clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
@@ -202,7 +202,7 @@ groupReplacements(const TUReplacements &TUs, const TUDiagnostics &TUDs,
 
 bool mergeAndDeduplicate(const TUReplacements &TUs, const TUDiagnostics &TUDs,
                          FileToChangesMap &FileChanges,
-                         clang::SourceManager &SM) {
+                         clang::SourceManager &SM, bool IgnoreInsertConflict) {
   auto GroupedReplacements = groupReplacements(TUs, TUDs, SM);
   bool ConflictDetected = false;
 
@@ -231,7 +231,24 @@ bool mergeAndDeduplicate(const TUReplacements &TUs, const TUDiagnostics &TUDs,
         // For now, printing directly the error reported by `AtomicChange` is
         // the easiest solution.
         errs() << llvm::toString(std::move(Err)) << "\n";
-        ConflictDetected = true;
+        if (IgnoreInsertConflict) {
+          tooling::Replacements &Replacements = FileChange.getReplacements();
+          unsigned NewOffset =
+              Replacements.getShiftedCodePosition(R.getOffset());
+          unsigned NewLength = Replacements.getShiftedCodePosition(
+                                   R.getOffset() + R.getLength()) -
+                               NewOffset;
+          if (NewLength == R.getLength()) {
+            tooling::Replacement RR = tooling::Replacement(
+                R.getFilePath(), NewOffset, NewLength, R.getReplacementText());
+            Replacements = Replacements.merge(tooling::Replacements(RR));
+          } else {
+            llvm::errs()
+                << "Can't resolve conflict, skipping the replacement.\n";
+            ConflictDetected = true;
+          }
+        } else
+          ConflictDetected = true;
       }
     }
     FileChanges.try_emplace(Entry,

diff  --git a/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp b/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
index 52ef725352d0b..68e7feaa3baed 100644
--- a/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
+++ b/clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
@@ -42,6 +42,11 @@ static cl::opt<bool> RemoveTUReplacementFiles(
              "merging/replacing."),
     cl::init(false), cl::cat(ReplacementCategory));
 
+static cl::opt<bool> IgnoreInsertConflict(
+    "ignore-insert-conflict",
+    cl::desc("Ignore insert conflict and keep running to fix."),
+    cl::init(false), cl::cat(ReplacementCategory));
+
 static cl::opt<bool> DoFormat(
     "format",
     cl::desc("Enable formatting of code changed by applying replacements.\n"
@@ -131,7 +136,7 @@ int main(int argc, char **argv) {
   SourceManager SM(Diagnostics, Files);
 
   FileToChangesMap Changes;
-  if (!mergeAndDeduplicate(TURs, TUDs, Changes, SM))
+  if (!mergeAndDeduplicate(TURs, TUDs, Changes, SM, IgnoreInsertConflict))
     return 1;
 
   tooling::ApplyChangesSpec Spec;

diff  --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
index fdfe5a07bc551..821b941d4c383 100755
--- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
+++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
@@ -180,6 +180,7 @@ def find_binary(arg, name, build_path):
 def apply_fixes(args, clang_apply_replacements_binary, tmpdir):
   """Calls clang-apply-fixes on a given directory."""
   invocation = [clang_apply_replacements_binary]
+  invocation.append('-ignore-insert-conflict')
   if args.format:
     invocation.append('-format')
   if args.style:

diff  --git a/clang-tools-extra/test/clang-apply-replacements/Inputs/ignore-conflict/file1.yaml b/clang-tools-extra/test/clang-apply-replacements/Inputs/ignore-conflict/file1.yaml
new file mode 100644
index 0000000000000..a80cf82b2bf33
--- /dev/null
+++ b/clang-tools-extra/test/clang-apply-replacements/Inputs/ignore-conflict/file1.yaml
@@ -0,0 +1,24 @@
+---
+MainSourceFile:     ignore-conflict.cpp
+Diagnostics:
+  - DiagnosticName: test-ignore-conflict-insertion
+    DiagnosticMessage:
+      Message: Fix
+      FilePath: $(path)/ignore-conflict.cpp
+      FileOffset: 0
+      Replacements:
+        - FilePath:        $(path)/ignore-conflict.cpp
+          Offset:          0
+          Length:          0
+          ReplacementText: "#include <a.h>\n"
+  - DiagnosticName: test-ignore-conflict-insertion
+    DiagnosticMessage:
+      Message: Fix
+      FilePath: $(path)/ignore-conflict.cpp
+      FileOffset: 0
+      Replacements:
+        - FilePath:        $(path)/ignore-conflict.cpp
+          Offset:          0
+          Length:          0
+          ReplacementText: "#include <b.h>\n"
+...

diff  --git a/clang-tools-extra/test/clang-apply-replacements/Inputs/ignore-conflict/ignore-conflict.cpp b/clang-tools-extra/test/clang-apply-replacements/Inputs/ignore-conflict/ignore-conflict.cpp
new file mode 100644
index 0000000000000..8791dd952319d
--- /dev/null
+++ b/clang-tools-extra/test/clang-apply-replacements/Inputs/ignore-conflict/ignore-conflict.cpp
@@ -0,0 +1,4 @@
+class MyType {};
+// CHECK: #include <a.h>
+// CHECK-NEXT: #include <b.h>
+// CEHCK-NEXT: class MyType {};

diff  --git a/clang-tools-extra/test/clang-apply-replacements/ignore-conflict.cpp b/clang-tools-extra/test/clang-apply-replacements/ignore-conflict.cpp
new file mode 100644
index 0000000000000..4e681dd15f0db
--- /dev/null
+++ b/clang-tools-extra/test/clang-apply-replacements/ignore-conflict.cpp
@@ -0,0 +1,5 @@
+// RUN: mkdir -p %T/Inputs/ignore-conflict
+// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/ignore-conflict/ignore-conflict.cpp > %T/Inputs/ignore-conflict/ignore-conflict.cpp
+// RUN: sed "s#\$(path)#%/T/Inputs/ignore-conflict#" %S/Inputs/ignore-conflict/file1.yaml > %T/Inputs/ignore-conflict/file1.yaml
+// RUN: clang-apply-replacements --ignore-insert-conflict %T/Inputs/ignore-conflict
+// RUN: FileCheck -input-file=%T/Inputs/ignore-conflict/ignore-conflict.cpp %S/Inputs/ignore-conflict/ignore-conflict.cpp

diff  --git a/clang/include/clang/Tooling/Refactoring/AtomicChange.h b/clang/include/clang/Tooling/Refactoring/AtomicChange.h
index 3945a7c9fefbd..92f322ef7d80b 100644
--- a/clang/include/clang/Tooling/Refactoring/AtomicChange.h
+++ b/clang/include/clang/Tooling/Refactoring/AtomicChange.h
@@ -116,6 +116,8 @@ class AtomicChange {
   /// Returns a const reference to existing replacements.
   const Replacements &getReplacements() const { return Replaces; }
 
+  Replacements &getReplacements() { return Replaces; }
+
   llvm::ArrayRef<std::string> getInsertedHeaders() const {
     return InsertedHeaders;
   }


        


More information about the cfe-commits mailing list