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" 50 using namespace clang;
52 static llvm::cl::extrahelp
CommonHelp(CommonOptionsParser::HelpMessage);
55 static llvm::cl::opt<std::string>
56 ProjectName(
"project-name", llvm::cl::desc(
"Name of project."),
61 llvm::cl::desc(
"Continue if files are not mapped correctly."),
64 static llvm::cl::opt<std::string>
66 llvm::cl::desc(
"Directory for outputting generated files."),
69 static llvm::cl::opt<bool>
70 PublicOnly(
"public", llvm::cl::desc(
"Document only public declarations."),
75 llvm::cl::desc(
"Use only doxygen-style comments to generate docs."),
79 "stylesheets", llvm::cl::CommaSeparated,
80 llvm::cl::desc(
"CSS stylesheets to extend the default styles."),
83 static llvm::cl::opt<std::string>
SourceRoot(
"source-root", llvm::cl::desc(R
"( 84 Directory where processed files are stored. 85 Links to definition locations will only be 86 generated if the file is in this dir.)"), 89 static llvm::cl::opt<std::string>
91 URL of repository that hosts code. 92 Used for links to definition locations.)"), 101 static llvm::cl::opt<OutputFormatTy>
102 FormatEnum(
"format", llvm::cl::desc(
"Format for outputted docs."),
104 "Documentation in YAML format."),
106 "Documentation in MD format."),
108 "Documentation in HTML format.")),
121 llvm_unreachable(
"Unknown OutputFormatTy");
130 return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
133 bool CreateDirectory(
const Twine &DirName,
bool ClearDirectory =
false) {
135 llvm::SmallString<128> DocsRootPath;
136 if (ClearDirectory) {
137 std::error_code RemoveStatus = llvm::sys::fs::remove_directories(DirName);
138 if (RemoveStatus != OK) {
139 llvm::errs() <<
"Unable to remove existing documentation directory for " 144 std::error_code DirectoryStatus = llvm::sys::fs::create_directories(DirName);
145 if (DirectoryStatus != OK) {
146 llvm::errs() <<
"Unable to create documentation directories.\n";
168 StringRef RelativePath,
171 llvm::SmallString<128>
Path;
172 llvm::sys::path::native(Root, Path);
173 llvm::sys::path::append(Path, RelativePath);
175 return llvm::createStringError(llvm::inconvertibleErrorCode(),
176 "failed to create directory");
177 llvm::sys::path::append(
Path,
Name + Ext);
181 int main(
int argc,
const char **argv) {
182 llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
185 ExecutorName.setInitialValue(
"all-TUs");
186 auto Exec = clang::tooling::createExecutorFromCommandLineArgs(
190 llvm::errs() <<
toString(Exec.takeError()) <<
"\n";
196 llvm::outs() <<
"Emiting docs in " << Format <<
" format.\n";
199 llvm::errs() <<
toString(G.takeError()) <<
"\n";
203 ArgumentsAdjuster ArgAdjuster;
205 ArgAdjuster = combineAdjusters(
206 getInsertArgumentAdjuster(
"-fparse-all-comments",
207 tooling::ArgumentInsertPosition::END),
211 Exec->get()->getExecutionContext(),
218 {
"index.js",
"index_json.js"}};
220 if (Format ==
"html") {
223 llvm::SmallString<128> AssetsPath;
224 llvm::sys::path::native(ClangDocPath, AssetsPath);
225 AssetsPath = llvm::sys::path::parent_path(AssetsPath);
226 llvm::sys::path::append(AssetsPath,
"..",
"share",
"clang");
227 llvm::SmallString<128> DefaultStylesheet;
228 llvm::sys::path::native(AssetsPath, DefaultStylesheet);
229 llvm::sys::path::append(DefaultStylesheet,
230 "clang-doc-default-stylesheet.css");
231 llvm::SmallString<128> IndexJS;
232 llvm::sys::path::native(AssetsPath, IndexJS);
233 llvm::sys::path::append(IndexJS,
"index.js");
235 DefaultStylesheet.str());
240 llvm::outs() <<
"Mapping decls...\n";
245 llvm::errs() <<
"Error mapping decls in files. Clang-doc will ignore " 246 "these files and continue:\n" 247 <<
toString(std::move(Err)) <<
"\n";
249 llvm::errs() <<
toString(std::move(Err)) <<
"\n";
257 llvm::outs() <<
"Collecting infos...\n";
258 llvm::StringMap<std::vector<StringRef>> USRToBitcode;
259 Exec->get()->getToolResults()->forEachResult(
260 [&](StringRef Key, StringRef Value) {
261 auto R = USRToBitcode.try_emplace(Key, std::vector<StringRef>());
262 R.first->second.emplace_back(Value);
266 llvm::outs() <<
"Reducing " << USRToBitcode.size() <<
" infos...\n";
267 std::atomic<bool> Error;
269 llvm::sys::Mutex IndexMutex;
271 llvm::ThreadPool Pool(ExecutorConcurrency == 0 ? llvm::hardware_concurrency()
272 : ExecutorConcurrency);
273 for (
auto &Group : USRToBitcode) {
275 std::vector<std::unique_ptr<doc::Info>> Infos;
277 for (
auto &Bitcode : Group.getValue()) {
278 llvm::BitstreamCursor Stream(Bitcode);
280 auto ReadInfos = Reader.readBitcode();
282 llvm::errs() <<
toString(ReadInfos.takeError()) <<
"\n";
286 std::move(ReadInfos->begin(), ReadInfos->end(),
287 std::back_inserter(Infos));
300 llvm::errs() <<
toString(InfoPath.takeError()) <<
"\n";
304 std::error_code FileErr;
305 llvm::raw_fd_ostream InfoOS(InfoPath.get(), FileErr,
306 llvm::sys::fs::OF_None);
308 llvm::errs() <<
"Error opening info file: " << FileErr.message()
318 if (
auto Err = G->get()->generateDocForInfo(I, InfoOS, CDCtx))
319 llvm::errs() <<
toString(std::move(Err)) <<
"\n";
328 llvm::outs() <<
"Generating assets for docs...\n";
329 Err = G->get()->createResources(CDCtx);
331 llvm::errs() <<
toString(std::move(Err)) <<
"\n";
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::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< std::string > RepositoryUrl("repository", llvm::cl::desc(R"(
URL of repository that hosts code.
Used for links to definition locations.)"), llvm::cl::cat(ClangDocCategory))
llvm::SmallString< 16 > extractName() const
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
bool CreateDirectory(const Twine &DirName, bool ClearDirectory=false)
std::vector< HeaderHandle > Path
static llvm::cl::opt< bool > PublicOnly("public", llvm::cl::desc("Document only public declarations."), llvm::cl::init(false), llvm::cl::cat(ClangDocCategory))
static llvm::cl::opt< std::string > ProjectName("project-name", llvm::cl::desc("Name of project."), llvm::cl::cat(ClangDocCategory))
llvm::Expected< std::unique_ptr< Generator > > findGeneratorByName(llvm::StringRef Format)
std::string GetExecutablePath(const char *Argv0, void *MainAddr)
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::extrahelp CommonHelp(CommonOptionsParser::HelpMessage)
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))
int main(int argc, const char **argv)
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))
std::vector< std::string > UserStylesheets
llvm::Expected< std::unique_ptr< Info > > mergeInfos(std::vector< std::unique_ptr< Info >> &Values)
static constexpr llvm::StringLiteral Name
std::string getFormatString()
llvm::SmallString< 128 > Path
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))
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Expected< llvm::SmallString< 128 > > getInfoOutputFile(StringRef Root, StringRef RelativePath, StringRef Name, StringRef Ext)
static void addInfoToIndex(Index &Idx, const doc::Info *Info)
static llvm::cl::OptionCategory ClangDocCategory("clang-doc options")
std::unique_ptr< tooling::FrontendActionFactory > newMapperActionFactory(ClangDocContext CDCtx)
std::vector< std::string > FilesToCopy