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,
33 StringRef HTMLRootPath);
36 return createFileError(
"cannot open file " + FileName, EC);
43 StringMap<std::unique_ptr<doc::Info>> Infos,
51 BumpPtrAllocator Allocator;
55 std::unique_ptr<MemoryBuffer> Buffer;
58 static Expected<std::unique_ptr<MustacheTemplateFile>>
60 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError =
61 MemoryBuffer::getFile(FileName);
62 if (
auto EC = BufferOrError.getError())
64 return std::make_unique<MustacheTemplateFile>(
65 std::move(BufferOrError.get()));
69 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError =
70 MemoryBuffer::getFile(FileName);
71 if (
auto EC = BufferOrError.getError())
74 std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrError.get());
75 StringRef FileContent = Buffer->getBuffer();
76 T.registerPartial(Name.str(), FileContent.str());
77 return Error::success();
80 void render(json::Value &V, raw_ostream &OS) { T.render(V, OS); }
83 : Saver(Allocator), Ctx(Allocator, Saver), T(B->getBuffer(), Ctx),
84 Buffer(std::
move(B)) {}
93 StringRef TemplatePath,
94 std::vector<std::pair<StringRef, StringRef>> Partials) {
96 if (Error Err = T.takeError())
98 Template = std::move(T.get());
99 for (
const auto &[Name, FileName] : Partials)
100 if (
auto Err = Template->registerPartialFile(Name, FileName))
102 return Error::success();
108 auto ConvertToNative = [](std::string &&Path) -> std::string {
109 SmallString<128> PathBuf(Path);
110 llvm::sys::path::native(PathBuf);
111 return PathBuf.str().str();
114 std::string NamespaceFilePath =
116 std::string ClassFilePath =
118 std::string CommentFilePath =
120 std::string FunctionFilePath =
122 std::string EnumFilePath =
124 std::vector<std::pair<StringRef, StringRef>> Partials = {
125 {
"Comments", CommentFilePath},
126 {
"FunctionPartial", FunctionFilePath},
127 {
"EnumPartial", EnumFilePath}};
135 return Error::success();
139 StringRef RootDir, StringMap<std::unique_ptr<doc::Info>> Infos,
142 llvm::TimeTraceScope TS(
"Setup Templates");
148 llvm::TimeTraceScope TS(
"Generate JSON for Mustache");
151 RootDir, std::move(Infos), CDCtx))
156 SmallString<128> JSONPath;
157 sys::path::native(RootDir.str() +
"/json", JSONPath);
160 llvm::TimeTraceScope TS(
"Iterate JSON files");
162 sys::fs::recursive_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::recursive_directory_iterator()) {
173 if (JSONIter->type() == sys::fs::file_type::directory_file) {
174 SmallString<128> HTMLClonedPath(JSONIter->path());
175 sys::path::replace_path_prefix(HTMLClonedPath, JSONPath, HTMLDirPath);
176 if (
auto EC = sys::fs::create_directories(HTMLClonedPath))
177 return createFileError(HTMLClonedPath, EC);
181 return createFileError(
"Failed to iterate: " + JSONIter->path(), EC);
183 auto Path = StringRef(JSONIter->path());
184 if (!Path.ends_with(
".json")) {
185 JSONIter.increment(EC);
189 auto File = MemoryBuffer::getFile(Path);
190 if (EC = File.getError(); EC)
193 llvm::errs() <<
"Failed to open file: " << Path <<
" " << EC.message()
196 auto Parsed = json::parse((*File)->getBuffer());
198 return Parsed.takeError();
200 std::error_code FileErr;
201 SmallString<128> HTMLFilePath(JSONIter->path());
202 sys::path::replace_path_prefix(HTMLFilePath, JSONPath, HTMLDirPath);
203 sys::path::replace_extension(HTMLFilePath,
"html");
204 raw_fd_ostream InfoOS(HTMLFilePath, FileErr, sys::fs::OF_None);
210 HTMLFilePath, InfoOS, CDCtx, HTMLDirPath))
212 JSONIter.increment(EC);
216 return Error::success();
220 SmallString<128> RelativeHTMLPath) {
221 V.getAsObject()->insert({
"ProjectName", CDCtx.
ProjectName});
222 json::Value StylesheetArr = Array();
223 sys::path::native(RelativeHTMLPath, sys::path::Style::posix);
225 auto *SSA = StylesheetArr.getAsArray();
228 SmallString<128> StylesheetPath = RelativeHTMLPath;
229 sys::path::append(StylesheetPath, sys::path::Style::posix,
230 sys::path::filename(FilePath));
231 SSA->emplace_back(StylesheetPath);
233 V.getAsObject()->insert({
"Stylesheets", StylesheetArr});
235 json::Value ScriptArr = Array();
236 auto *SCA = ScriptArr.getAsArray();
239 SmallString<128> JsPath = RelativeHTMLPath;
240 sys::path::append(JsPath, sys::path::Style::posix,
241 sys::path::filename(Script));
242 SCA->emplace_back(JsPath);
244 V.getAsObject()->insert({
"Scripts", ScriptArr});
245 return Error::success();
249 StringRef Path, raw_fd_ostream &OS,
251 StringRef HTMLRootPath) {
252 auto StrValue = (*
JSON.getAsObject())[
"InfoType"];
253 if (StrValue.kind() != json::Value::Kind::String)
254 return createStringError(
"JSON file '%s' does not contain key: 'InfoType'.",
255 Filename.str().c_str());
256 auto ObjTypeStr = StrValue.getAsString();
257 if (!ObjTypeStr.has_value())
258 return createStringError(
259 "JSON file '%s' does not contain 'InfoType' field as a string.",
260 Filename.str().c_str());
262 SmallString<128> PathVec(Path);
264 sys::path::remove_filename(PathVec);
266 if (ObjTypeStr.value() ==
"namespace") {
271 }
else if (ObjTypeStr.value() ==
"record") {
277 return Error::success();
293 return createStringError(inconvertibleErrorCode(),
"unexpected InfoType");
295 return Error::success();
301 if (Error Err =
copyFile(FilePath, ResourcePath))
303 for (
const auto &FilePath : CDCtx.
JsScripts)
304 if (Error Err =
copyFile(FilePath, ResourcePath))
306 return Error::success();
311static 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 generateDocForJSON(json::Value &JSON, StringRef Filename, StringRef Path, raw_fd_ostream &OS, const ClangDocContext &CDCtx, StringRef HTMLRootPath)
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)
llvm::SmallString< 128 > computeRelativePath(llvm::StringRef Destination, llvm::StringRef Origin)
static std::unique_ptr< MustacheTemplateFile > RecordTemplate
static GeneratorRegistry::Add< JSONGenerator > JSON(JSONGenerator::Format, "Generator for JSON output.")
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
static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V, SmallString< 128 > RelativeHTMLPath)
===– 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