18#include "llvm/Support/Error.h"
19#include "llvm/Support/MemoryBuffer.h"
20#include "llvm/Support/Mustache.h"
21#include "llvm/Support/Path.h"
22#include "llvm/Support/TimeProfiler.h"
25using namespace llvm::json;
26using namespace llvm::mustache;
31 StringRef Path, raw_fd_ostream &OS,
35 return createFileError(
"cannot open file " + FileName, EC);
42 StringMap<std::unique_ptr<doc::Info>> Infos,
50 BumpPtrAllocator Allocator;
54 std::unique_ptr<MemoryBuffer> Buffer;
57 static Expected<std::unique_ptr<MustacheTemplateFile>>
59 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError =
60 MemoryBuffer::getFile(FileName);
61 if (
auto EC = BufferOrError.getError())
63 return std::make_unique<MustacheTemplateFile>(
64 std::move(BufferOrError.get()));
68 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError =
69 MemoryBuffer::getFile(FileName);
70 if (
auto EC = BufferOrError.getError())
73 std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrError.get());
74 StringRef FileContent = Buffer->getBuffer();
75 T.registerPartial(Name.str(), FileContent.str());
76 return Error::success();
79 void render(json::Value &V, raw_ostream &OS) { T.render(V, OS); }
82 : Saver(Allocator), Ctx(Allocator, Saver), T(B->getBuffer(), Ctx),
83 Buffer(std::
move(B)) {}
92 StringRef TemplatePath,
93 std::vector<std::pair<StringRef, StringRef>> Partials) {
95 if (Error Err = T.takeError())
97 Template = std::move(T.get());
98 for (
const auto &[Name, FileName] : Partials)
99 if (
auto Err = Template->registerPartialFile(Name, FileName))
101 return Error::success();
107 auto ConvertToNative = [](std::string &&Path) -> std::string {
108 SmallString<128> PathBuf(Path);
109 llvm::sys::path::native(PathBuf);
110 return PathBuf.str().str();
113 std::string NamespaceFilePath =
115 std::string ClassFilePath =
117 std::string CommentFilePath =
119 std::string FunctionFilePath =
121 std::string EnumFilePath =
123 std::vector<std::pair<StringRef, StringRef>> Partials = {
124 {
"Comments", CommentFilePath},
125 {
"FunctionPartial", FunctionFilePath},
126 {
"EnumPartial", EnumFilePath}};
134 return Error::success();
138 StringRef RootDir, StringMap<std::unique_ptr<doc::Info>> Infos,
141 llvm::TimeTraceScope TS(
"Setup Templates");
147 llvm::TimeTraceScope TS(
"Generate JSON for Mustache");
150 RootDir, std::move(Infos), CDCtx))
155 SmallString<128> JSONPath;
156 sys::path::native(RootDir.str() +
"/json", JSONPath);
158 StringMap<json::Value> JSONFileMap;
160 llvm::TimeTraceScope TS(
"Iterate JSON files");
162 sys::fs::directory_iterator JSONIter(JSONPath, EC);
163 std::vector<json::Value> JSONFiles;
164 JSONFiles.reserve(Infos.size());
166 return createStringError(
"Failed to create directory iterator.");
168 SmallString<128> HTMLDirPath(RootDir.str() +
"/html/");
169 if (
auto EC = sys::fs::create_directories(HTMLDirPath))
170 return createFileError(HTMLDirPath, EC);
171 while (JSONIter != sys::fs::directory_iterator()) {
173 return createFileError(
"Failed to iterate: " + JSONIter->path(), EC);
175 auto Path = StringRef(JSONIter->path());
176 if (!Path.ends_with(
".json")) {
177 JSONIter.increment(EC);
181 auto File = MemoryBuffer::getFile(Path);
182 if (EC = File.getError(); EC)
185 llvm::errs() <<
"Failed to open file: " << Path <<
" " << EC.message()
188 auto Parsed = json::parse((*File)->getBuffer());
190 return Parsed.takeError();
192 std::error_code FileErr;
193 SmallString<128> HTMLFilePath(HTMLDirPath);
194 sys::path::append(HTMLFilePath, sys::path::filename(Path));
195 sys::path::replace_extension(HTMLFilePath,
"html");
196 raw_fd_ostream InfoOS(HTMLFilePath, FileErr, sys::fs::OF_None);
201 HTMLFilePath, InfoOS, CDCtx))
203 JSONIter.increment(EC);
207 return Error::success();
211 V.getAsObject()->insert({
"ProjectName", CDCtx.
ProjectName});
212 json::Value StylesheetArr = Array();
213 SmallString<128> RelativePath(
"./");
214 sys::path::native(RelativePath, sys::path::Style::posix);
216 auto *SSA = StylesheetArr.getAsArray();
219 SmallString<128> StylesheetPath = RelativePath;
220 sys::path::append(StylesheetPath, sys::path::Style::posix,
221 sys::path::filename(FilePath));
222 SSA->emplace_back(StylesheetPath);
224 V.getAsObject()->insert({
"Stylesheets", StylesheetArr});
226 json::Value ScriptArr = Array();
227 auto *SCA = ScriptArr.getAsArray();
230 SmallString<128> JsPath = RelativePath;
231 sys::path::append(JsPath, sys::path::Style::posix,
232 sys::path::filename(Script));
233 SCA->emplace_back(JsPath);
235 V.getAsObject()->insert({
"Scripts", ScriptArr});
236 return Error::success();
240 StringRef Path, raw_fd_ostream &OS,
242 auto StrValue = (*
JSON.getAsObject())[
"InfoType"];
243 if (StrValue.kind() != json::Value::Kind::String)
244 return createStringError(
"JSON file '%s' does not contain key: 'InfoType'.",
245 Filename.str().c_str());
246 auto ObjTypeStr = StrValue.getAsString();
247 if (!ObjTypeStr.has_value())
248 return createStringError(
249 "JSON file '%s' does not contain 'InfoType' field as a string.",
250 Filename.str().c_str());
252 if (ObjTypeStr.value() ==
"namespace") {
257 }
else if (ObjTypeStr.value() ==
"record") {
263 return Error::success();
279 return createStringError(inconvertibleErrorCode(),
"unexpected InfoType");
281 return Error::success();
287 if (Error Err =
copyFile(FilePath, ResourcePath))
289 for (
const auto &FilePath : CDCtx.
JsScripts)
290 if (Error Err =
copyFile(FilePath, ResourcePath))
292 return Error::success();
297static GeneratorRegistry::Add<MustacheHTMLGenerator>
Error generateDocs(StringRef RootDir, llvm::StringMap< std::unique_ptr< doc::Info > > Infos, const ClangDocContext &CDCtx) override
static const char * Format
Error createResources(ClangDocContext &CDCtx) override
Error generateDocs(StringRef RootDir, StringMap< std::unique_ptr< doc::Info > > Infos, const ClangDocContext &CDCtx) override
Error generateDocForInfo(Info *I, raw_ostream &OS, const ClangDocContext &CDCtx) override
static Expected< std::unique_ptr< MustacheTemplateFile > > createMustacheFile(StringRef FileName)
Error registerPartialFile(StringRef Name, StringRef FileName)
void render(json::Value &V, raw_ostream &OS)
MustacheTemplateFile(std::unique_ptr< MemoryBuffer > &&B)
llvm::Error copyFile(llvm::StringRef FilePath, llvm::StringRef OutDirectory)
static Error setupTemplateFiles(const clang::doc::ClangDocContext &CDCtx)
static Error setupTemplate(std::unique_ptr< MustacheTemplateFile > &Template, StringRef TemplatePath, std::vector< std::pair< StringRef, StringRef > > Partials)
llvm::Expected< std::unique_ptr< Generator > > findGeneratorByName(llvm::StringRef Format)
static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V)
static std::unique_ptr< MustacheTemplateFile > RecordTemplate
static GeneratorRegistry::Add< JSONGenerator > JSON(JSONGenerator::Format, "Generator for JSON output.")
static Error generateDocForJSON(json::Value &JSON, StringRef Filename, StringRef Path, raw_fd_ostream &OS, const ClangDocContext &CDCtx)
static GeneratorRegistry::Add< MustacheHTMLGenerator > MHTML(MustacheHTMLGenerator::Format, "Generator for mustache HTML output.")
static std::unique_ptr< MustacheTemplateFile > NamespaceTemplate
static Error createFileOpenError(StringRef FileName, std::error_code EC)
volatile int MHTMLGeneratorAnchorSource
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Some operations such as code completion produce a set of candidates.
std::vector< std::string > UserStylesheets
llvm::StringMap< std::string > MustacheTemplates
std::vector< std::string > JsScripts