25#include "clang/AST/AST.h"
26#include "clang/AST/Decl.h"
27#include "clang/ASTMatchers/ASTMatchFinder.h"
28#include "clang/ASTMatchers/ASTMatchersInternal.h"
29#include "clang/Driver/Options.h"
30#include "clang/Frontend/FrontendActions.h"
31#include "clang/Tooling/AllTUsExecution.h"
32#include "clang/Tooling/CommonOptionsParser.h"
33#include "clang/Tooling/Execution.h"
34#include "clang/Tooling/Tooling.h"
35#include "llvm/ADT/APFloat.h"
36#include "llvm/Support/CommandLine.h"
37#include "llvm/Support/Error.h"
38#include "llvm/Support/FileSystem.h"
39#include "llvm/Support/Mutex.h"
40#include "llvm/Support/Path.h"
41#include "llvm/Support/Process.h"
42#include "llvm/Support/Signals.h"
43#include "llvm/Support/ThreadPool.h"
44#include "llvm/Support/raw_ostream.h"
53static llvm::cl::extrahelp
CommonHelp(CommonOptionsParser::HelpMessage);
56static llvm::cl::opt<std::string>
57 ProjectName(
"project-name", llvm::cl::desc(
"Name of project."),
62 llvm::cl::desc(
"Continue if files are not mapped correctly."),
65static llvm::cl::opt<std::string>
67 llvm::cl::desc(
"Directory for outputting generated files."),
70static llvm::cl::opt<bool>
71 PublicOnly(
"public", llvm::cl::desc(
"Document only public declarations."),
76 llvm::cl::desc(
"Use only doxygen-style comments to generate docs."),
80 "stylesheets", llvm::cl::CommaSeparated,
81 llvm::cl::desc(
"CSS stylesheets to extend the default styles."),
84static llvm::cl::opt<std::string>
SourceRoot(
"source-root", llvm::cl::desc(R
"(
85Directory where processed files are stored.
86Links to definition locations will only be
87generated if the file is in this dir.)"),
90static llvm::cl::opt<std::string>
92URL of repository that hosts code.
93Used for links to definition locations.)"),
102static llvm::cl::opt<OutputFormatTy>
103 FormatEnum(
"format", llvm::cl::desc(
"Format for outputted docs."),
105 "Documentation in YAML format."),
107 "Documentation in MD format."),
109 "Documentation in HTML format.")),
122 llvm_unreachable(
"Unknown OutputFormatTy");
131 return llvm::sys::fs::getMainExecutable(
Argv0, MainAddr);
134int main(
int argc,
const char **argv) {
135 llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
138 const char *Overview =
139 R
"(Generates documentation from source code and comments.
141Example usage for files without flags (default):
143 $ clang-doc File1.cpp File2.cpp ... FileN.cpp
145Example usage for a project using a compile commands database:
147 $ clang-doc --executor=all-TUs compile_commands.json
150 auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
154 llvm::errs() << toString(Executor.takeError()) <<
"\n";
160 llvm::outs() <<
"Emiting docs in " << Format <<
" format.\n";
163 llvm::errs() << toString(G.takeError()) <<
"\n";
167 ArgumentsAdjuster ArgAdjuster;
169 ArgAdjuster = combineAdjusters(
170 getInsertArgumentAdjuster(
"-fparse-all-comments",
171 tooling::ArgumentInsertPosition::END),
175 Executor->get()->getExecutionContext(),
182 {
"index.js",
"index_json.js"}};
184 if (Format ==
"html") {
187 llvm::SmallString<128> NativeClangDocPath;
188 llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
189 llvm::SmallString<128> AssetsPath;
190 AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
191 llvm::sys::path::append(AssetsPath,
"..",
"share",
"clang");
192 llvm::SmallString<128> DefaultStylesheet;
193 llvm::sys::path::native(AssetsPath, DefaultStylesheet);
194 llvm::sys::path::append(DefaultStylesheet,
195 "clang-doc-default-stylesheet.css");
196 llvm::SmallString<128> IndexJS;
197 llvm::sys::path::native(AssetsPath, IndexJS);
198 llvm::sys::path::append(IndexJS,
"index.js");
200 std::string(DefaultStylesheet.str()));
205 llvm::outs() <<
"Mapping decls...\n";
210 llvm::errs() <<
"Error mapping decls in files. Clang-doc will ignore "
211 "these files and continue:\n"
212 << toString(std::move(Err)) <<
"\n";
214 llvm::errs() << toString(std::move(Err)) <<
"\n";
222 llvm::outs() <<
"Collecting infos...\n";
223 llvm::StringMap<std::vector<StringRef>> USRToBitcode;
224 Executor->get()->getToolResults()->forEachResult(
225 [&](StringRef Key, StringRef Value) {
226 auto R = USRToBitcode.try_emplace(Key, std::vector<StringRef>());
227 R.first->second.emplace_back(Value);
232 llvm::sys::Mutex USRToInfoMutex;
233 llvm::StringMap<std::unique_ptr<doc::Info>> USRToInfo;
236 llvm::outs() <<
"Reducing " << USRToBitcode.size() <<
" infos...\n";
237 std::atomic<bool>
Error;
239 llvm::sys::Mutex IndexMutex;
241 llvm::ThreadPool Pool(llvm::hardware_concurrency(ExecutorConcurrency));
242 for (
auto &Group : USRToBitcode) {
244 std::vector<std::unique_ptr<doc::Info>> Infos;
246 for (
auto &Bitcode : Group.getValue()) {
247 llvm::BitstreamCursor Stream(Bitcode);
248 doc::ClangDocBitcodeReader Reader(Stream);
249 auto ReadInfos = Reader.readBitcode();
251 llvm::errs() << toString(ReadInfos.takeError()) <<
"\n";
255 std::move(ReadInfos->begin(), ReadInfos->end(),
256 std::back_inserter(Infos));
261 llvm::errs() << llvm::toString(Reduced.takeError());
267 std::lock_guard<llvm::sys::Mutex> Guard(IndexMutex);
273 std::lock_guard<llvm::sys::Mutex> Guard(USRToInfoMutex);
274 USRToInfo[Group.getKey()] = std::move(Reduced.get());
285 if (std::error_code Err = llvm::sys::fs::create_directories(
OutDirectory);
286 Err != std::error_code()) {
287 llvm::errs() <<
"Failed to create directory '" <<
OutDirectory <<
"'\n";
292 llvm::outs() <<
"Generating docs...\n";
294 G->get()->generateDocs(
OutDirectory, std::move(USRToInfo), CDCtx)) {
295 llvm::errs() << toString(std::move(Err)) <<
"\n";
299 llvm::outs() <<
"Generating assets for docs...\n";
300 Err = G->get()->createResources(CDCtx);
302 llvm::errs() << toString(std::move(Err)) <<
"\n";
static llvm::cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage)
static llvm::cl::opt< bool > PublicOnly("public", llvm::cl::desc("Document only public declarations."), llvm::cl::init(false), llvm::cl::cat(ClangDocCategory))
int main(int argc, const char **argv)
static llvm::cl::opt< std::string > ProjectName("project-name", llvm::cl::desc("Name of project."), llvm::cl::cat(ClangDocCategory))
std::string GetExecutablePath(const char *Argv0, void *MainAddr)
static llvm::cl::opt< OutputFormatTy > FormatEnum("format", llvm::cl::desc("Format for outputted docs."), llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", "Documentation in YAML format."), clEnumValN(OutputFormatTy::md, "md", "Documentation in MD format."), clEnumValN(OutputFormatTy::html, "html", "Documentation in HTML format.")), llvm::cl::init(OutputFormatTy::yaml), llvm::cl::cat(ClangDocCategory))
static llvm::cl::list< std::string > UserStylesheets("stylesheets", llvm::cl::CommaSeparated, llvm::cl::desc("CSS stylesheets to extend the default styles."), llvm::cl::cat(ClangDocCategory))
static llvm::cl::opt< std::string > SourceRoot("source-root", llvm::cl::desc(R"(
Directory where processed files are stored.
Links to definition locations will only be
generated if the file is in this dir.)"), llvm::cl::cat(ClangDocCategory))
static llvm::cl::opt< bool > IgnoreMappingFailures("ignore-map-errors", llvm::cl::desc("Continue if files are not mapped correctly."), llvm::cl::init(true), llvm::cl::cat(ClangDocCategory))
static llvm::cl::opt< std::string > OutDirectory("output", llvm::cl::desc("Directory for outputting generated files."), llvm::cl::init("docs"), llvm::cl::cat(ClangDocCategory))
static llvm::cl::opt< bool > DoxygenOnly("doxygen", llvm::cl::desc("Use only doxygen-style comments to generate docs."), llvm::cl::init(false), llvm::cl::cat(ClangDocCategory))
static llvm::cl::OptionCategory ClangDocCategory("clang-doc options")
static llvm::cl::opt< std::string > RepositoryUrl("repository", llvm::cl::desc(R"(
URL of repository that hosts code.
Used for links to definition locations.)"), llvm::cl::cat(ClangDocCategory))
std::string getFormatString()
static constexpr llvm::SourceMgr::DiagKind Error
static void addInfoToIndex(Index &Idx, const doc::Info *Info)
llvm::Expected< std::unique_ptr< Info > > mergeInfos(std::vector< std::unique_ptr< Info > > &Values)
std::unique_ptr< tooling::FrontendActionFactory > newMapperActionFactory(ClangDocContext CDCtx)
llvm::Expected< std::unique_ptr< Generator > > findGeneratorByName(llvm::StringRef Format)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::vector< std::string > UserStylesheets
std::vector< std::string > FilesToCopy