https://github.com/zeyi2 updated 
https://github.com/llvm/llvm-project/pull/169640

>From 0bcc0a061e4c03f85a2f7481591e97779785f731 Mon Sep 17 00:00:00 2001
From: mtx <[email protected]>
Date: Mon, 24 Nov 2025 10:14:58 +0800
Subject: [PATCH 1/6] [Tooling] Fix misleading progress report when files have
 multiple compile commands

---
 clang/lib/Tooling/Tooling.cpp | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 9bae12454d2dc..491294b731e85 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -37,6 +37,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/OptTable.h"
@@ -96,7 +97,7 @@ static bool ignoreExtraCC1Commands(const driver::Compilation 
*Compilation) {
       OffloadCompilation = true;
 
   if (Jobs.size() > 1) {
-    for (auto *A : Actions){
+    for (auto *A : Actions) {
       // On MacOSX real actions may end up being wrapped in BindArchAction
       if (isa<driver::BindArchAction>(A))
         A = *A->input_begin();
@@ -413,8 +414,8 @@ bool ToolInvocation::run() {
       Driver->BuildCompilation(llvm::ArrayRef(Argv)));
   if (!Compilation)
     return false;
-  const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
-      &*Diagnostics, Compilation.get());
+  const llvm::opt::ArgStringList *const CC1Args =
+      getCC1Arguments(&*Diagnostics, Compilation.get());
   if (!CC1Args)
     return false;
   std::unique_ptr<CompilerInvocation> Invocation(
@@ -497,9 +498,7 @@ void ClangTool::appendArgumentsAdjuster(ArgumentsAdjuster 
Adjuster) {
   ArgsAdjuster = combineAdjusters(std::move(ArgsAdjuster), 
std::move(Adjuster));
 }
 
-void ClangTool::clearArgumentsAdjusters() {
-  ArgsAdjuster = nullptr;
-}
+void ClangTool::clearArgumentsAdjusters() { ArgsAdjuster = nullptr; }
 
 static void injectResourceDir(CommandLineArguments &Args, const char *Argv0,
                               void *MainAddr) {
@@ -555,8 +554,9 @@ int ClangTool::run(ToolAction *Action) {
   }
 
   size_t NumOfTotalFiles = AbsolutePaths.size();
-  unsigned ProcessedFileCounter = 0;
+  unsigned CurrentFileIndex = 0;
   for (llvm::StringRef File : AbsolutePaths) {
+    ++CurrentFileIndex; // Increment file counter once per file.
     // Currently implementations of CompilationDatabase::getCompileCommands can
     // change the state of the file system (e.g.  prepare generated headers), 
so
     // this method needs to run right before we invoke the tool, as the next
@@ -571,6 +571,7 @@ int ClangTool::run(ToolAction *Action) {
       FileSkipped = true;
       continue;
     }
+    unsigned CurrentCommandIndexForFile = 0;
     for (CompileCommand &CompileCommand : CompileCommandsForFile) {
       // If the 'directory' field of the compilation database is empty, display
       // an error and use the working directory instead.
@@ -617,12 +618,16 @@ int ClangTool::run(ToolAction *Action) {
       // pass in made-up names here. Make sure this works on other platforms.
       injectResourceDir(CommandLine, "clang_tool", &StaticSymbol);
 
+      ++CurrentCommandIndexForFile;
+
       // FIXME: We need a callback mechanism for the tool writer to output a
       // customized message for each file.
-      if (NumOfTotalFiles > 1)
-        llvm::errs() << "[" + std::to_string(++ProcessedFileCounter) + "/" +
-                            std::to_string(NumOfTotalFiles) +
-                            "] Processing file " + File
+      if (NumOfTotalFiles > 1 || CompileCommandsForFile.size() > 1)
+        llvm::errs() << "[" + std::to_string(CurrentFileIndex) + "/" +
+                            std::to_string(NumOfTotalFiles) + "] (" +
+                            std::to_string(CurrentCommandIndexForFile) + "/" +
+                            std::to_string(CompileCommandsForFile.size()) +
+                            ") Processing file " + File
                      << ".\n";
       ToolInvocation Invocation(std::move(CommandLine), Action, Files.get(),
                                 PCHContainerOps);

>From 3df57dec9880788efb6dbd50892fdf5f8a0d3b79 Mon Sep 17 00:00:00 2001
From: mtx <[email protected]>
Date: Thu, 27 Nov 2025 18:14:10 +0800
Subject: [PATCH 2/6] Fix printing format

---
 clang/lib/Tooling/Tooling.cpp | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 491294b731e85..2914da9a21888 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -556,7 +556,7 @@ int ClangTool::run(ToolAction *Action) {
   size_t NumOfTotalFiles = AbsolutePaths.size();
   unsigned CurrentFileIndex = 0;
   for (llvm::StringRef File : AbsolutePaths) {
-    ++CurrentFileIndex; // Increment file counter once per file.
+    ++CurrentFileIndex;
     // Currently implementations of CompilationDatabase::getCompileCommands can
     // change the state of the file system (e.g.  prepare generated headers), 
so
     // this method needs to run right before we invoke the tool, as the next
@@ -622,13 +622,17 @@ int ClangTool::run(ToolAction *Action) {
 
       // FIXME: We need a callback mechanism for the tool writer to output a
       // customized message for each file.
-      if (NumOfTotalFiles > 1 || CompileCommandsForFile.size() > 1)
+      if (NumOfTotalFiles > 1 || CompileCommandsForFile.size() > 1) {
         llvm::errs() << "[" + std::to_string(CurrentFileIndex) + "/" +
-                            std::to_string(NumOfTotalFiles) + "] (" +
-                            std::to_string(CurrentCommandIndexForFile) + "/" +
-                            std::to_string(CompileCommandsForFile.size()) +
-                            ") Processing file " + File
-                     << ".\n";
+                            std::to_string(NumOfTotalFiles) + "]";
+        if (CompileCommandsForFile.size() > 1) {
+          llvm::errs() << " (" + std::to_string(CurrentCommandIndexForFile) +
+                              "/" +
+                              std::to_string(CompileCommandsForFile.size()) +
+                              ")";
+        }
+        llvm::errs() << " Processing file " + File << ".\n";
+      }
       ToolInvocation Invocation(std::move(CommandLine), Action, Files.get(),
                                 PCHContainerOps);
       Invocation.setDiagnosticConsumer(DiagConsumer);

>From 9ee5bf8a9fa8d7227a65d3be9da602958c9cd0e7 Mon Sep 17 00:00:00 2001
From: mtx <[email protected]>
Date: Fri, 28 Nov 2025 15:55:14 +0800
Subject: [PATCH 3/6] Remove header

---
 clang/lib/Tooling/Tooling.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 2914da9a21888..1e5c71da960e8 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -37,7 +37,6 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/OptTable.h"

>From 32238aaf19a6e7bd9045b6e098c227ecbce478a1 Mon Sep 17 00:00:00 2001
From: mtx <[email protected]>
Date: Sun, 7 Dec 2025 19:21:27 +0800
Subject: [PATCH 4/6] Add testcases

---
 clang/unittests/Tooling/ToolingTest.cpp | 188 ++++++++++++++++++++++++
 1 file changed, 188 insertions(+)

diff --git a/clang/unittests/Tooling/ToolingTest.cpp 
b/clang/unittests/Tooling/ToolingTest.cpp
index 25e1d67eb2294..4fe4598c89a81 100644
--- a/clang/unittests/Tooling/ToolingTest.cpp
+++ b/clang/unittests/Tooling/ToolingTest.cpp
@@ -20,6 +20,7 @@
 #include "clang/Testing/CommandLineArgs.h"
 #include "clang/Tooling/ArgumentsAdjusters.h"
 #include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/JSONCompilationDatabase.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Path.h"
@@ -1034,5 +1035,192 @@ TEST(runToolOnCode, TestResetDiagnostics) {
                     "void func() { long x; Foo f(x); }"));
 }
 
+TEST(ClangToolTest, ProgressReportSingleFile) {
+  SmallString<32> BaseDir;
+  llvm::sys::path::system_temp_directory(false, BaseDir);
+  llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix);
+  std::string BaseDirStr(BaseDir);
+
+  std::string File = BaseDirStr + "/test.cpp";
+
+  std::string ErrorMessage;
+  std::string JSONDatabase = R"json([
+  {
+    "directory": "%DIR%",
+    "command": "clang++ -c test.cpp",
+    "file": "test.cpp"
+  }])json";
+
+  {
+    size_t Pos = JSONDatabase.find("%DIR%");
+    ASSERT_NE(Pos, std::string::npos);
+    JSONDatabase.replace(Pos, 5, BaseDirStr);
+  }
+
+  std::unique_ptr<CompilationDatabase> Database(
+      JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
+                                              JSONCommandLineSyntax::Gnu));
+  ASSERT_TRUE(Database);
+
+  ClangTool Tool(*Database, {File});
+  Tool.mapVirtualFile(File, "int x;");
+
+  testing::internal::CaptureStderr();
+  Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
+  std::string Output = testing::internal::GetCapturedStderr();
+
+  EXPECT_TRUE(Output.empty());
+}
+
+TEST(ClangToolTest, ProgressReportMultipleFiles) {
+  SmallString<32> BaseDir;
+  llvm::sys::path::system_temp_directory(false, BaseDir);
+  llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix);
+  std::string BaseDirStr(BaseDir);
+
+  std::string File1 = BaseDirStr + "/test1.cpp";
+  std::string File2 = BaseDirStr + "/test2.cpp";
+
+  std::string ErrorMessage;
+  std::string JSONDatabase = R"json([
+  {
+    "directory": "%DIR%",
+    "command": "clang++ -c test1.cpp",
+    "file": "test1.cpp"
+  },
+  {
+    "directory": "%DIR%",
+    "command": "clang++ -c test2.cpp",
+    "file": "test2.cpp"
+  }])json";
+
+  for (size_t Pos = 0;
+       (Pos = JSONDatabase.find("%DIR%", Pos)) != std::string::npos;) {
+    JSONDatabase.replace(Pos, 5, BaseDirStr);
+    Pos += BaseDirStr.size();
+  }
+
+  std::unique_ptr<CompilationDatabase> Database(
+      JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
+                                              JSONCommandLineSyntax::Gnu));
+  ASSERT_TRUE(Database);
+
+  ClangTool Tool(*Database, {File1, File2});
+  Tool.mapVirtualFile(File1, "int x;");
+  Tool.mapVirtualFile(File2, "int y;");
+
+  testing::internal::CaptureStderr();
+  Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
+  std::string Output = testing::internal::GetCapturedStderr();
+
+  std::string Expected = "[1/2] Processing file " + File1 + ".\n" +
+                         "[2/2] Processing file " + File2 + ".\n";
+  EXPECT_EQ(Output, Expected);
+}
+
+TEST(ClangToolTest, ProgressReportMultipleCommands) {
+  SmallString<32> BaseDir;
+  llvm::sys::path::system_temp_directory(false, BaseDir);
+  llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix);
+  std::string BaseDirStr(BaseDir);
+
+  std::string File = BaseDirStr + "/test.cpp";
+
+  std::string ErrorMessage;
+  std::string JSONDatabase = R"json([
+  {
+    "directory": "%DIR%",
+    "command": "clang++ -c test.cpp -DCMD1",
+    "file": "test.cpp"
+  },
+  {
+    "directory": "%DIR%",
+    "command": "clang++ -c test.cpp -DCMD2",
+    "file": "test.cpp"
+  }])json";
+
+  for (size_t Pos = 0;
+       (Pos = JSONDatabase.find("%DIR%", Pos)) != std::string::npos;) {
+    JSONDatabase.replace(Pos, 5, BaseDirStr);
+    Pos += BaseDirStr.size();
+  }
+
+  std::unique_ptr<CompilationDatabase> Database(
+      JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
+                                              JSONCommandLineSyntax::Gnu));
+  ASSERT_TRUE(Database);
+
+  ClangTool Tool(*Database, {File});
+  Tool.mapVirtualFile(File, "int x;");
+
+  testing::internal::CaptureStderr();
+  Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
+  std::string Output = testing::internal::GetCapturedStderr();
+
+  std::string Expected = "[1/1] (1/2) Processing file " + File + ".\n" +
+                         "[1/1] (2/2) Processing file " + File + ".\n";
+  EXPECT_EQ(Output, Expected);
+}
+
+TEST(ClangToolTest, ProgressReportMixed) {
+  SmallString<32> BaseDir;
+  llvm::sys::path::system_temp_directory(false, BaseDir);
+  llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix);
+  std::string BaseDirStr(BaseDir);
+
+  std::string File1 = BaseDirStr + "/test1.cpp";
+  std::string File2 = BaseDirStr + "/test2.cpp";
+  std::string File3 = BaseDirStr + "/test3.cpp";
+
+  std::string ErrorMessage;
+  std::string JSONDatabase = R"json([
+  {
+    "directory": "%DIR%",
+    "command": "clang++ -c test1.cpp",
+    "file": "test1.cpp"
+  },
+  {
+    "directory": "%DIR%",
+    "command": "clang++ -c test2.cpp -DCMD1",
+    "file": "test2.cpp"
+  },
+  {
+    "directory": "%DIR%",
+    "command": "clang++ -c test2.cpp -DCMD2",
+    "file": "test2.cpp"
+  },
+  {
+    "directory": "%DIR%",
+    "command": "clang++ -c test3.cpp",
+    "file": "test3.cpp"
+  }])json";
+
+  for (size_t Pos = 0;
+       (Pos = JSONDatabase.find("%DIR%", Pos)) != std::string::npos;) {
+    JSONDatabase.replace(Pos, 5, BaseDirStr);
+    Pos += BaseDirStr.size();
+  }
+
+  std::unique_ptr<CompilationDatabase> Database(
+      JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
+                                              JSONCommandLineSyntax::Gnu));
+  ASSERT_TRUE(Database);
+
+  ClangTool Tool(*Database, {File1, File2, File3});
+  Tool.mapVirtualFile(File1, "int x;");
+  Tool.mapVirtualFile(File2, "int y;");
+  Tool.mapVirtualFile(File3, "int z;");
+
+  testing::internal::CaptureStderr();
+  Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
+  std::string Output = testing::internal::GetCapturedStderr();
+
+  std::string Expected = "[1/3] Processing file " + File1 + ".\n" +
+                         "[2/3] (1/2) Processing file " + File2 + ".\n" +
+                         "[2/3] (2/2) Processing file " + File2 + ".\n" +
+                         "[3/3] Processing file " + File3 + ".\n";
+  EXPECT_EQ(Output, Expected);
+}
+
 } // end namespace tooling
 } // end namespace clang

>From 5c469cd476e56ceaefbed581737dec6b51fc119d Mon Sep 17 00:00:00 2001
From: mtx <[email protected]>
Date: Sun, 7 Dec 2025 22:01:28 +0800
Subject: [PATCH 5/6] Fix test on Windows

---
 clang/unittests/Tooling/ToolingTest.cpp | 31 ++++++++++++++++++-------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/clang/unittests/Tooling/ToolingTest.cpp 
b/clang/unittests/Tooling/ToolingTest.cpp
index 4fe4598c89a81..bb33f98a1ff23 100644
--- a/clang/unittests/Tooling/ToolingTest.cpp
+++ b/clang/unittests/Tooling/ToolingTest.cpp
@@ -1113,8 +1113,13 @@ TEST(ClangToolTest, ProgressReportMultipleFiles) {
   Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
   std::string Output = testing::internal::GetCapturedStderr();
 
-  std::string Expected = "[1/2] Processing file " + File1 + ".\n" +
-                         "[2/2] Processing file " + File2 + ".\n";
+  SmallString<32> NativeFile1(File1);
+  llvm::sys::path::native(NativeFile1);
+  SmallString<32> NativeFile2(File2);
+  llvm::sys::path::native(NativeFile2);
+  std::string Expected = "[1/2] Processing file " + std::string(NativeFile1) +
+                         ".\n" + "[2/2] Processing file " +
+                         std::string(NativeFile2) + ".\n";
   EXPECT_EQ(Output, Expected);
 }
 
@@ -1157,8 +1162,11 @@ TEST(ClangToolTest, ProgressReportMultipleCommands) {
   Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
   std::string Output = testing::internal::GetCapturedStderr();
 
-  std::string Expected = "[1/1] (1/2) Processing file " + File + ".\n" +
-                         "[1/1] (2/2) Processing file " + File + ".\n";
+  SmallString<32> NativeFile(File);
+  llvm::sys::path::native(NativeFile);
+  std::string Expected =
+      "[1/1] (1/2) Processing file " + std::string(NativeFile) + ".\n" +
+      "[1/1] (2/2) Processing file " + std::string(NativeFile) + ".\n";
   EXPECT_EQ(Output, Expected);
 }
 
@@ -1215,10 +1223,17 @@ TEST(ClangToolTest, ProgressReportMixed) {
   Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
   std::string Output = testing::internal::GetCapturedStderr();
 
-  std::string Expected = "[1/3] Processing file " + File1 + ".\n" +
-                         "[2/3] (1/2) Processing file " + File2 + ".\n" +
-                         "[2/3] (2/2) Processing file " + File2 + ".\n" +
-                         "[3/3] Processing file " + File3 + ".\n";
+  SmallString<32> NativeFile1(File1);
+  llvm::sys::path::native(NativeFile1);
+  SmallString<32> NativeFile2(File2);
+  llvm::sys::path::native(NativeFile2);
+  SmallString<32> NativeFile3(File3);
+  llvm::sys::path::native(NativeFile3);
+  std::string Expected =
+      "[1/3] Processing file " + std::string(NativeFile1) + ".\n" +
+      "[2/3] (1/2) Processing file " + std::string(NativeFile2) + ".\n" +
+      "[2/3] (2/2) Processing file " + std::string(NativeFile2) + ".\n" +
+      "[3/3] Processing file " + std::string(NativeFile3) + ".\n";
   EXPECT_EQ(Output, Expected);
 }
 

>From bcc74bbf7b1f2ccef345e4c2eaec1fc485a1836d Mon Sep 17 00:00:00 2001
From: mtx <[email protected]>
Date: Wed, 10 Dec 2025 04:39:30 +0800
Subject: [PATCH 6/6] cleanup

---
 clang/unittests/Tooling/ToolingTest.cpp | 285 +++++++++---------------
 1 file changed, 110 insertions(+), 175 deletions(-)

diff --git a/clang/unittests/Tooling/ToolingTest.cpp 
b/clang/unittests/Tooling/ToolingTest.cpp
index bb33f98a1ff23..64e85e57f4671 100644
--- a/clang/unittests/Tooling/ToolingTest.cpp
+++ b/clang/unittests/Tooling/ToolingTest.cpp
@@ -23,6 +23,7 @@
 #include "clang/Tooling/JSONCompilationDatabase.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/JSON.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/TargetParser/Host.h"
@@ -56,15 +57,16 @@ class TestAction : public clang::ASTFrontendAction {
 };
 
 class FindTopLevelDeclConsumer : public clang::ASTConsumer {
- public:
+public:
   explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl)
       : FoundTopLevelDecl(FoundTopLevelDecl) {}
   bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) override {
     *FoundTopLevelDecl = true;
     return true;
   }
- private:
-  bool * const FoundTopLevelDecl;
+
+private:
+  bool *const FoundTopLevelDecl;
 };
 } // end namespace
 
@@ -79,26 +81,27 @@ TEST(runToolOnCode, FindsNoTopLevelDeclOnEmptyCode) {
 
 namespace {
 class FindClassDeclXConsumer : public clang::ASTConsumer {
- public:
+public:
   FindClassDeclXConsumer(bool *FoundClassDeclX)
       : FoundClassDeclX(FoundClassDeclX) {}
   bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) override {
-    if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(
-            *GroupRef.begin())) {
+    if (CXXRecordDecl *Record =
+            dyn_cast<clang::CXXRecordDecl>(*GroupRef.begin())) {
       if (Record->getName() == "X") {
         *FoundClassDeclX = true;
       }
     }
     return true;
   }
- private:
+
+private:
   bool *FoundClassDeclX;
 };
 bool FindClassDeclX(ASTUnit *AST) {
   for (std::vector<Decl *>::iterator i = AST->top_level_begin(),
                                      e = AST->top_level_end();
        i != e; ++i) {
-    if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(*i)) {
+    if (CXXRecordDecl *Record = dyn_cast<clang::CXXRecordDecl>(*i)) {
       if (Record->getName() == "X") {
         return true;
       }
@@ -563,12 +566,14 @@ TEST(runToolOnCode, TestSkipFunctionBody) {
       std::make_unique<SkipBodyAction>(),
       "struct skipMe { skipMe() : an_error() { more error } };", Args));
   EXPECT_TRUE(runToolOnCodeWithArgs(
-      std::make_unique<SkipBodyAction>(), "struct skipMe { skipMe(); };"
-                          "skipMe::skipMe() : an_error([](){;}) { more error 
}",
+      std::make_unique<SkipBodyAction>(),
+      "struct skipMe { skipMe(); };"
+      "skipMe::skipMe() : an_error([](){;}) { more error }",
       Args));
   EXPECT_TRUE(runToolOnCodeWithArgs(
-      std::make_unique<SkipBodyAction>(), "struct skipMe { skipMe(); };"
-                          "skipMe::skipMe() : an_error{[](){;}} { more error 
}",
+      std::make_unique<SkipBodyAction>(),
+      "struct skipMe { skipMe(); };"
+      "skipMe::skipMe() : an_error{[](){;}} { more error }",
       Args));
   EXPECT_TRUE(runToolOnCodeWithArgs(
       std::make_unique<SkipBodyAction>(),
@@ -576,12 +581,12 @@ TEST(runToolOnCode, TestSkipFunctionBody) {
       "skipMe::skipMe() : a<b<c>(e)>>(), f{}, g() { error }",
       Args));
   EXPECT_TRUE(runToolOnCodeWithArgs(
-      std::make_unique<SkipBodyAction>(), "struct skipMe { skipMe() : 
bases()... { error } };",
-      Args));
+      std::make_unique<SkipBodyAction>(),
+      "struct skipMe { skipMe() : bases()... { error } };", Args));
 
   EXPECT_FALSE(runToolOnCodeWithArgs(
-      std::make_unique<SkipBodyAction>(), "struct skipMeNot { skipMeNot() : 
an_error() { } };",
-      Args));
+      std::make_unique<SkipBodyAction>(),
+      "struct skipMeNot { skipMeNot() : an_error() { } };", Args));
   EXPECT_FALSE(runToolOnCodeWithArgs(std::make_unique<SkipBodyAction>(),
                                      "struct skipMeNot { skipMeNot(); };"
                                      "skipMeNot::skipMeNot() : an_error() { }",
@@ -603,9 +608,10 @@ TEST(runToolOnCode, TestSkipFunctionBody) {
       "void skipMe() try something;")); // don't crash while parsing
 
   // Template
-  EXPECT_TRUE(runToolOnCode(
-      std::make_unique<SkipBodyAction>(), "template<typename T> int skipMe() { 
an_error_here }"
-                          "int x = skipMe<int>();"));
+  EXPECT_TRUE(
+      runToolOnCode(std::make_unique<SkipBodyAction>(),
+                    "template<typename T> int skipMe() { an_error_here }"
+                    "int x = skipMe<int>();"));
   EXPECT_FALSE(runToolOnCodeWithArgs(
       std::make_unique<SkipBodyAction>(),
       "template<typename T> int skipMeNot() { an_error_here }", Args2));
@@ -626,7 +632,8 @@ TEST(runToolOnCodeWithArgs, TestNoDepFile) {
   Args.push_back(std::string(DepFilePath.str()));
   Args.push_back("-MF");
   Args.push_back(std::string(DepFilePath.str()));
-  EXPECT_TRUE(runToolOnCodeWithArgs(std::make_unique<SkipBodyAction>(), "", 
Args));
+  EXPECT_TRUE(
+      runToolOnCodeWithArgs(std::make_unique<SkipBodyAction>(), "", Args));
   EXPECT_FALSE(llvm::sys::fs::exists(DepFilePath.str()));
   EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
 }
@@ -684,11 +691,11 @@ TEST(ClangToolTest, ArgumentAdjusters) {
   bool Ran = false;
   ArgumentsAdjuster CheckSyntaxOnlyAdjuster =
       [&Found, &Ran](const CommandLineArguments &Args, StringRef /*unused*/) {
-    Ran = true;
-    if (llvm::is_contained(Args, "-fsyntax-only"))
-      Found = true;
-    return Args;
-  };
+        Ran = true;
+        if (llvm::is_contained(Args, "-fsyntax-only"))
+          Found = true;
+        return Args;
+      };
   Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster);
   Tool.run(Action.get());
   EXPECT_TRUE(Ran);
@@ -792,10 +799,10 @@ TEST(ClangToolTest, StripDependencyFileAdjuster) {
 
   CommandLineArguments FinalArgs;
   ArgumentsAdjuster CheckFlagsAdjuster =
-    [&FinalArgs](const CommandLineArguments &Args, StringRef /*unused*/) {
-      FinalArgs = Args;
-      return Args;
-    };
+      [&FinalArgs](const CommandLineArguments &Args, StringRef /*unused*/) {
+        FinalArgs = Args;
+        return Args;
+      };
   Tool.clearArgumentsAdjusters();
   Tool.appendArgumentsAdjuster(getClangStripDependencyFileAdjuster());
   Tool.appendArgumentsAdjuster(CheckFlagsAdjuster);
@@ -1035,88 +1042,82 @@ TEST(runToolOnCode, TestResetDiagnostics) {
                     "void func() { long x; Foo f(x); }"));
 }
 
-TEST(ClangToolTest, ProgressReportSingleFile) {
-  SmallString<32> BaseDir;
-  llvm::sys::path::system_temp_directory(false, BaseDir);
-  llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix);
-  std::string BaseDirStr(BaseDir);
-
-  std::string File = BaseDirStr + "/test.cpp";
+namespace {
+struct TestCommand {
+  llvm::StringRef File;
+  llvm::StringRef Command;
+};
 
+std::string runToolWithProgress(llvm::ArrayRef<TestCommand> Commands,
+                                llvm::StringRef BaseDir) {
   std::string ErrorMessage;
-  std::string JSONDatabase = R"json([
-  {
-    "directory": "%DIR%",
-    "command": "clang++ -c test.cpp",
-    "file": "test.cpp"
-  }])json";
-
-  {
-    size_t Pos = JSONDatabase.find("%DIR%");
-    ASSERT_NE(Pos, std::string::npos);
-    JSONDatabase.replace(Pos, 5, BaseDirStr);
+
+  llvm::json::Array Entries;
+  for (const auto &Cmd : Commands) {
+    Entries.push_back(llvm::json::Object{
+        {"directory", BaseDir}, {"command", Cmd.Command}, {"file", Cmd.File}});
   }
+  std::string DatabaseContent;
+  llvm::raw_string_ostream OS(DatabaseContent);
+  OS << llvm::json::Value(std::move(Entries));
 
   std::unique_ptr<CompilationDatabase> Database(
-      JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
+      JSONCompilationDatabase::loadFromBuffer(DatabaseContent, ErrorMessage,
                                               JSONCommandLineSyntax::Gnu));
-  ASSERT_TRUE(Database);
+  if (!Database) {
+    ADD_FAILURE() << "Failed to load compilation database: " << ErrorMessage;
+    return "";
+  }
 
-  ClangTool Tool(*Database, {File});
-  Tool.mapVirtualFile(File, "int x;");
+  std::vector<std::string> AbsoluteFiles;
+  for (const auto &Cmd : Commands) {
+    SmallString<32> NativeFile(BaseDir);
+    llvm::sys::path::append(NativeFile, Cmd.File);
+    llvm::sys::path::native(NativeFile);
+    std::string AbsPath = std::string(NativeFile);
+    if (AbsoluteFiles.empty() || AbsoluteFiles.back() != AbsPath) {
+      AbsoluteFiles.push_back(AbsPath);
+    }
+  }
+
+  ClangTool Tool(*Database, AbsoluteFiles);
+  for (const auto &F : AbsoluteFiles) {
+    Tool.mapVirtualFile(F, "int x;");
+  }
 
   testing::internal::CaptureStderr();
   Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
-  std::string Output = testing::internal::GetCapturedStderr();
-
-  EXPECT_TRUE(Output.empty());
+  return testing::internal::GetCapturedStderr();
 }
+} // namespace
 
-TEST(ClangToolTest, ProgressReportMultipleFiles) {
+TEST(ClangToolTest, ProgressReportSingleFile) {
   SmallString<32> BaseDir;
   llvm::sys::path::system_temp_directory(false, BaseDir);
   llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix);
-  std::string BaseDirStr(BaseDir);
-
-  std::string File1 = BaseDirStr + "/test1.cpp";
-  std::string File2 = BaseDirStr + "/test2.cpp";
-
-  std::string ErrorMessage;
-  std::string JSONDatabase = R"json([
-  {
-    "directory": "%DIR%",
-    "command": "clang++ -c test1.cpp",
-    "file": "test1.cpp"
-  },
-  {
-    "directory": "%DIR%",
-    "command": "clang++ -c test2.cpp",
-    "file": "test2.cpp"
-  }])json";
-
-  for (size_t Pos = 0;
-       (Pos = JSONDatabase.find("%DIR%", Pos)) != std::string::npos;) {
-    JSONDatabase.replace(Pos, 5, BaseDirStr);
-    Pos += BaseDirStr.size();
-  }
 
-  std::unique_ptr<CompilationDatabase> Database(
-      JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
-                                              JSONCommandLineSyntax::Gnu));
-  ASSERT_TRUE(Database);
+  EXPECT_TRUE(
+      runToolWithProgress({{"test.cpp", "clang++ -c test.cpp"}}, BaseDir)
+          .empty());
+}
 
-  ClangTool Tool(*Database, {File1, File2});
-  Tool.mapVirtualFile(File1, "int x;");
-  Tool.mapVirtualFile(File2, "int y;");
+TEST(ClangToolTest, ProgressReportMultipleFiles) {
+  SmallString<32> BaseDir;
+  llvm::sys::path::system_temp_directory(false, BaseDir);
+  llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix);
 
-  testing::internal::CaptureStderr();
-  Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
-  std::string Output = testing::internal::GetCapturedStderr();
+  std::string Output =
+      runToolWithProgress({{"test1.cpp", "clang++ -c test1.cpp"},
+                           {"test2.cpp", "clang++ -c test2.cpp"}},
+                          BaseDir);
 
-  SmallString<32> NativeFile1(File1);
+  SmallString<32> NativeFile1(BaseDir);
+  llvm::sys::path::append(NativeFile1, "test1.cpp");
   llvm::sys::path::native(NativeFile1);
-  SmallString<32> NativeFile2(File2);
+  SmallString<32> NativeFile2(BaseDir);
+  llvm::sys::path::append(NativeFile2, "test2.cpp");
   llvm::sys::path::native(NativeFile2);
+
   std::string Expected = "[1/2] Processing file " + std::string(NativeFile1) +
                          ".\n" + "[2/2] Processing file " +
                          std::string(NativeFile2) + ".\n";
@@ -1127,42 +1128,14 @@ TEST(ClangToolTest, ProgressReportMultipleCommands) {
   SmallString<32> BaseDir;
   llvm::sys::path::system_temp_directory(false, BaseDir);
   llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix);
-  std::string BaseDirStr(BaseDir);
-
-  std::string File = BaseDirStr + "/test.cpp";
-
-  std::string ErrorMessage;
-  std::string JSONDatabase = R"json([
-  {
-    "directory": "%DIR%",
-    "command": "clang++ -c test.cpp -DCMD1",
-    "file": "test.cpp"
-  },
-  {
-    "directory": "%DIR%",
-    "command": "clang++ -c test.cpp -DCMD2",
-    "file": "test.cpp"
-  }])json";
-
-  for (size_t Pos = 0;
-       (Pos = JSONDatabase.find("%DIR%", Pos)) != std::string::npos;) {
-    JSONDatabase.replace(Pos, 5, BaseDirStr);
-    Pos += BaseDirStr.size();
-  }
-
-  std::unique_ptr<CompilationDatabase> Database(
-      JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
-                                              JSONCommandLineSyntax::Gnu));
-  ASSERT_TRUE(Database);
 
-  ClangTool Tool(*Database, {File});
-  Tool.mapVirtualFile(File, "int x;");
+  std::string Output =
+      runToolWithProgress({{"test.cpp", "clang++ -c test.cpp -DCMD1"},
+                           {"test.cpp", "clang++ -c test.cpp -DCMD2"}},
+                          BaseDir);
 
-  testing::internal::CaptureStderr();
-  Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
-  std::string Output = testing::internal::GetCapturedStderr();
-
-  SmallString<32> NativeFile(File);
+  SmallString<32> NativeFile(BaseDir);
+  llvm::sys::path::append(NativeFile, "test.cpp");
   llvm::sys::path::native(NativeFile);
   std::string Expected =
       "[1/1] (1/2) Processing file " + std::string(NativeFile) + ".\n" +
@@ -1174,61 +1147,24 @@ TEST(ClangToolTest, ProgressReportMixed) {
   SmallString<32> BaseDir;
   llvm::sys::path::system_temp_directory(false, BaseDir);
   llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix);
-  std::string BaseDirStr(BaseDir);
-
-  std::string File1 = BaseDirStr + "/test1.cpp";
-  std::string File2 = BaseDirStr + "/test2.cpp";
-  std::string File3 = BaseDirStr + "/test3.cpp";
-
-  std::string ErrorMessage;
-  std::string JSONDatabase = R"json([
-  {
-    "directory": "%DIR%",
-    "command": "clang++ -c test1.cpp",
-    "file": "test1.cpp"
-  },
-  {
-    "directory": "%DIR%",
-    "command": "clang++ -c test2.cpp -DCMD1",
-    "file": "test2.cpp"
-  },
-  {
-    "directory": "%DIR%",
-    "command": "clang++ -c test2.cpp -DCMD2",
-    "file": "test2.cpp"
-  },
-  {
-    "directory": "%DIR%",
-    "command": "clang++ -c test3.cpp",
-    "file": "test3.cpp"
-  }])json";
-
-  for (size_t Pos = 0;
-       (Pos = JSONDatabase.find("%DIR%", Pos)) != std::string::npos;) {
-    JSONDatabase.replace(Pos, 5, BaseDirStr);
-    Pos += BaseDirStr.size();
-  }
-
-  std::unique_ptr<CompilationDatabase> Database(
-      JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
-                                              JSONCommandLineSyntax::Gnu));
-  ASSERT_TRUE(Database);
 
-  ClangTool Tool(*Database, {File1, File2, File3});
-  Tool.mapVirtualFile(File1, "int x;");
-  Tool.mapVirtualFile(File2, "int y;");
-  Tool.mapVirtualFile(File3, "int z;");
+  std::string Output =
+      runToolWithProgress({{"test1.cpp", "clang++ -c test1.cpp"},
+                           {"test2.cpp", "clang++ -c test2.cpp -DCMD1"},
+                           {"test2.cpp", "clang++ -c test2.cpp -DCMD2"},
+                           {"test3.cpp", "clang++ -c test3.cpp"}},
+                          BaseDir);
 
-  testing::internal::CaptureStderr();
-  Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
-  std::string Output = testing::internal::GetCapturedStderr();
-
-  SmallString<32> NativeFile1(File1);
+  SmallString<32> NativeFile1(BaseDir);
+  llvm::sys::path::append(NativeFile1, "test1.cpp");
   llvm::sys::path::native(NativeFile1);
-  SmallString<32> NativeFile2(File2);
+  SmallString<32> NativeFile2(BaseDir);
+  llvm::sys::path::append(NativeFile2, "test2.cpp");
   llvm::sys::path::native(NativeFile2);
-  SmallString<32> NativeFile3(File3);
+  SmallString<32> NativeFile3(BaseDir);
+  llvm::sys::path::append(NativeFile3, "test3.cpp");
   llvm::sys::path::native(NativeFile3);
+
   std::string Expected =
       "[1/3] Processing file " + std::string(NativeFile1) + ".\n" +
       "[2/3] (1/2) Processing file " + std::string(NativeFile2) + ".\n" +
@@ -1236,6 +1172,5 @@ TEST(ClangToolTest, ProgressReportMixed) {
       "[3/3] Processing file " + std::string(NativeFile3) + ".\n";
   EXPECT_EQ(Output, Expected);
 }
-
 } // end namespace tooling
 } // end namespace clang

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to