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
