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(). _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits