[clang-tools-extra] ff94ba6 - [clang-doc] Refactor error handling to use ExitOnError (#141699)
via cfe-commits
cfe-commits at lists.llvm.org
Fri May 30 13:34:18 PDT 2025
Author: Samarth Narang
Date: 2025-05-30T13:34:15-07:00
New Revision: ff94ba613e2fab918d5d96c57833ee3f6e3f3015
URL: https://github.com/llvm/llvm-project/commit/ff94ba613e2fab918d5d96c57833ee3f6e3f3015
DIFF: https://github.com/llvm/llvm-project/commit/ff94ba613e2fab918d5d96c57833ee3f6e3f3015.diff
LOG: [clang-doc] Refactor error handling to use ExitOnError (#141699)
This patch refactors the clang-doc tool to replace manual error handling
(e.g., checking error codes and calling exit()) with llvm::ExitOnError.
Fixes #140085
Added:
clang-tools-extra/test/clang-doc/invalid-options.cpp
Modified:
clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
index 41fbe87a713d9..8253ef298db4d 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -118,6 +118,8 @@ static llvm::cl::opt<OutputFormatTy> FormatEnum(
"Documentation in mustache HTML format")),
llvm::cl::init(OutputFormatTy::yaml), llvm::cl::cat(ClangDocCategory));
+static llvm::ExitOnError ExitOnErr;
+
static std::string getFormatString() {
switch (FormatEnum) {
case OutputFormatTy::yaml:
@@ -245,10 +247,30 @@ sortUsrToInfo(llvm::StringMap<std::unique_ptr<doc::Info>> &USRToInfo) {
}
}
+static llvm::Error handleMappingFailures(llvm::Error Err) {
+ if (!Err)
+ return llvm::Error::success();
+ if (IgnoreMappingFailures) {
+ llvm::errs() << "Error mapping decls in files. Clang-doc will ignore these "
+ "files and continue:\n"
+ << toString(std::move(Err)) << "\n";
+ return llvm::Error::success();
+ }
+ return Err;
+}
+
+static llvm::Error createDirectories(llvm::StringRef OutDirectory) {
+ if (std::error_code Err = llvm::sys::fs::create_directories(OutDirectory))
+ return llvm::createFileError(OutDirectory, Err);
+ return llvm::Error::success();
+}
+
int main(int argc, const char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
std::error_code OK;
+ ExitOnErr.setBanner("clang-doc error: ");
+
const char *Overview =
R"(Generates documentation from source code and comments.
@@ -261,22 +283,13 @@ Example usage for a project using a compile commands database:
$ clang-doc --executor=all-TUs compile_commands.json
)";
- auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
- argc, argv, ClangDocCategory, Overview);
-
- if (!Executor) {
- llvm::errs() << toString(Executor.takeError()) << "\n";
- return 1;
- }
+ auto Executor = ExitOnErr(clang::tooling::createExecutorFromCommandLineArgs(
+ argc, argv, ClangDocCategory, Overview));
// Fail early if an invalid format was provided.
std::string Format = getFormatString();
llvm::outs() << "Emiting docs in " << Format << " format.\n";
- auto G = doc::findGeneratorByName(Format);
- if (!G) {
- llvm::errs() << toString(G.takeError()) << "\n";
- return 1;
- }
+ auto G = ExitOnErr(doc::findGeneratorByName(Format));
ArgumentsAdjuster ArgAdjuster;
if (!DoxygenOnly)
@@ -286,7 +299,7 @@ Example usage for a project using a compile commands database:
ArgAdjuster);
clang::doc::ClangDocContext CDCtx = {
- Executor->get()->getExecutionContext(),
+ Executor->getExecutionContext(),
ProjectName,
PublicOnly,
OutDirectory,
@@ -297,40 +310,24 @@ Example usage for a project using a compile commands database:
{UserStylesheets.begin(), UserStylesheets.end()}};
if (Format == "html") {
- if (auto Err = getHtmlAssetFiles(argv[0], CDCtx)) {
- llvm::errs() << toString(std::move(Err)) << "\n";
- return 1;
- }
+ ExitOnErr(getHtmlAssetFiles(argv[0], CDCtx));
}
if (Format == "mustache") {
- if (auto Err = getMustacheHtmlFiles(argv[0], CDCtx)) {
- llvm::errs() << toString(std::move(Err)) << "\n";
- return 1;
- }
+ ExitOnErr(getMustacheHtmlFiles(argv[0], CDCtx));
}
// Mapping phase
llvm::outs() << "Mapping decls...\n";
- auto Err =
- Executor->get()->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster);
- if (Err) {
- if (IgnoreMappingFailures)
- llvm::errs() << "Error mapping decls in files. Clang-doc will ignore "
- "these files and continue:\n"
- << toString(std::move(Err)) << "\n";
- else {
- llvm::errs() << toString(std::move(Err)) << "\n";
- return 1;
- }
- }
+ ExitOnErr(handleMappingFailures(
+ Executor->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster)));
// Collect values into output by key.
// In ToolResults, the Key is the hashed USR and the value is the
// bitcode-encoded representation of the Info object.
llvm::outs() << "Collecting infos...\n";
llvm::StringMap<std::vector<StringRef>> USRToBitcode;
- Executor->get()->getToolResults()->forEachResult(
+ Executor->getToolResults()->forEachResult(
[&](StringRef Key, StringRef Value) {
USRToBitcode[Key].emplace_back(Value);
});
@@ -391,25 +388,13 @@ Example usage for a project using a compile commands database:
sortUsrToInfo(USRToInfo);
// Ensure the root output directory exists.
- if (std::error_code Err = llvm::sys::fs::create_directories(OutDirectory);
- Err != std::error_code()) {
- llvm::errs() << "Failed to create directory '" << OutDirectory << "'\n";
- return 1;
- }
+ ExitOnErr(createDirectories(OutDirectory));
// Run the generator.
llvm::outs() << "Generating docs...\n";
- if (auto Err =
- G->get()->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx)) {
- llvm::errs() << toString(std::move(Err)) << "\n";
- return 1;
- }
-
+ ExitOnErr(G->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx));
llvm::outs() << "Generating assets for docs...\n";
- Err = G->get()->createResources(CDCtx);
- if (Err) {
- llvm::outs() << "warning: " << toString(std::move(Err)) << "\n";
- }
+ ExitOnErr(G->createResources(CDCtx));
return 0;
}
diff --git a/clang-tools-extra/test/clang-doc/invalid-options.cpp b/clang-tools-extra/test/clang-doc/invalid-options.cpp
new file mode 100644
index 0000000000000..c8a4cef8364eb
--- /dev/null
+++ b/clang-tools-extra/test/clang-doc/invalid-options.cpp
@@ -0,0 +1,29 @@
+/// Invalid output path (%t is a file, not a directory).
+// RUN: rm -rf %t && touch %t
+// RUN: not clang-doc %s -output=%t/subdir 2>&1 | FileCheck %s --check-prefix=OUTPUT-FAIL
+// OUTPUT-FAIL: clang-doc error:
+// OUTPUT-FAIL: {{(Not a directory|no such file or directory)}}
+
+/// Invalid format option.
+// RUN: rm -rf %t && mkdir %t && touch %t/file
+// RUN: not clang-doc %s --output=%t/file -format=badformat 2>&1 | FileCheck %s --check-prefix=BAD-FORMAT
+// BAD-FORMAT: clang-doc: for the --format option: Cannot find option named 'badformat'!
+
+/// Missing HTML asset directory (warning only).
+// RUN: clang-doc %s -format=html -asset=%t/nonexistent-assets 2>&1 | FileCheck %s --check-prefix=ASSET-WARN
+// ASSET-WARN: Asset path supply is not a directory
+
+/// Mapping failure (with --ignore-map-errors=false).
+// RUN: not clang-doc %t/nonexistent.cpp -ignore-map-errors=false 2>&1 | FileCheck %s --check-prefix=MAP-FAIL
+// MAP-FAIL: clang-doc error: Failed to run action
+
+/// Mapping failure (with --ignore-map-errors=true).
+// RUN: clang-doc %t/nonexistent.cpp 2>&1 | FileCheck %s --check-prefix=MAP-WARN
+// MAP-WARN: Error mapping decls in files. Clang-doc will ignore these files and continue
+
+///Invalid executor type
+// RUN: not clang-doc --executor=invalid %s 2>&1 | FileCheck %s --check-prefix=EXECUTOR-FAIL
+// EXECUTOR-FAIL: clang-doc error:
+// EXECUTOR-FAIL: Executor "invalid" is not registered
+
+///TODO: Add tests for failures in generateDocs() and in createResources().
More information about the cfe-commits
mailing list