@@ -29,7 +29,8 @@ namespace clang {
2929namespace doc {
3030static Error generateDocForJSON (json::Value &JSON, StringRef Filename,
3131 StringRef Path, raw_fd_ostream &OS,
32- const ClangDocContext &CDCtx);
32+ const ClangDocContext &CDCtx,
33+ StringRef HTMLRootPath);
3334
3435static Error createFileOpenError (StringRef FileName, std::error_code EC) {
3536 return createFileError (" cannot open file " + FileName, EC);
@@ -159,16 +160,24 @@ Error MustacheHTMLGenerator::generateDocs(
159160 {
160161 llvm::TimeTraceScope TS (" Iterate JSON files" );
161162 std::error_code EC;
162- sys::fs::directory_iterator JSONIter (JSONPath, EC);
163+ sys::fs::recursive_directory_iterator JSONIter (JSONPath, EC);
163164 std::vector<json::Value> JSONFiles;
164165 JSONFiles.reserve (Infos.size ());
165166 if (EC)
166167 return createStringError (" Failed to create directory iterator." );
167168
168- SmallString<128 > HTMLDirPath (RootDir.str () + " /html/ " );
169+ SmallString<128 > HTMLDirPath (RootDir.str () + " /html" );
169170 if (auto EC = sys::fs::create_directories (HTMLDirPath))
170171 return createFileError (HTMLDirPath, EC);
171- while (JSONIter != sys::fs::directory_iterator ()) {
172+ while (JSONIter != sys::fs::recursive_directory_iterator ()) {
173+ // create the same directory structure in the HTML dir
174+ if (JSONIter->type () == sys::fs::file_type::directory_file) {
175+ SmallString<128 > HTMLClonedPath (JSONIter->path ());
176+ sys::path::replace_path_prefix (HTMLClonedPath, JSONPath, HTMLDirPath);
177+ if (auto EC = sys::fs::create_directories (HTMLClonedPath))
178+ return createFileError (HTMLClonedPath, EC);
179+ }
180+
172181 if (EC)
173182 return createFileError (" Failed to iterate: " + JSONIter->path (), EC);
174183
@@ -190,15 +199,16 @@ Error MustacheHTMLGenerator::generateDocs(
190199 return Parsed.takeError ();
191200
192201 std::error_code FileErr;
193- SmallString<128 > HTMLFilePath (HTMLDirPath );
194- sys::path::append (HTMLFilePath, sys::path::filename (Path) );
202+ SmallString<128 > HTMLFilePath (JSONIter-> path () );
203+ sys::path::replace_path_prefix (HTMLFilePath, JSONPath, HTMLDirPath );
195204 sys::path::replace_extension (HTMLFilePath, " html" );
196205 raw_fd_ostream InfoOS (HTMLFilePath, FileErr, sys::fs::OF_None);
197206 if (FileErr)
198207 return createFileOpenError (Path, FileErr);
199208
200- if (Error Err = generateDocForJSON (*Parsed, sys::path::stem (HTMLFilePath),
201- HTMLFilePath, InfoOS, CDCtx))
209+ if (Error Err =
210+ generateDocForJSON (*Parsed, sys::path::stem (HTMLFilePath),
211+ HTMLFilePath, InfoOS, CDCtx, HTMLDirPath))
202212 return Err;
203213 JSONIter.increment (EC);
204214 }
@@ -207,16 +217,16 @@ Error MustacheHTMLGenerator::generateDocs(
207217 return Error::success ();
208218}
209219
210- static Error setupTemplateValue (const ClangDocContext &CDCtx, json::Value &V) {
220+ static Error setupTemplateValue (const ClangDocContext &CDCtx, json::Value &V,
221+ SmallString<128 > RelativeHTMLPath) {
211222 V.getAsObject ()->insert ({" ProjectName" , CDCtx.ProjectName });
212223 json::Value StylesheetArr = Array ();
213- SmallString<128 > RelativePath (" ./" );
214- sys::path::native (RelativePath, sys::path::Style::posix);
224+ sys::path::native (RelativeHTMLPath, sys::path::Style::posix);
215225
216226 auto *SSA = StylesheetArr.getAsArray ();
217227 SSA->reserve (CDCtx.UserStylesheets .size ());
218228 for (const auto &FilePath : CDCtx.UserStylesheets ) {
219- SmallString<128 > StylesheetPath = RelativePath ;
229+ SmallString<128 > StylesheetPath = RelativeHTMLPath ;
220230 sys::path::append (StylesheetPath, sys::path::Style::posix,
221231 sys::path::filename (FilePath));
222232 SSA->emplace_back (StylesheetPath);
@@ -227,7 +237,7 @@ static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V) {
227237 auto *SCA = ScriptArr.getAsArray ();
228238 SCA->reserve (CDCtx.JsScripts .size ());
229239 for (auto Script : CDCtx.JsScripts ) {
230- SmallString<128 > JsPath = RelativePath ;
240+ SmallString<128 > JsPath = RelativeHTMLPath ;
231241 sys::path::append (JsPath, sys::path::Style::posix,
232242 sys::path::filename (Script));
233243 SCA->emplace_back (JsPath);
@@ -238,7 +248,8 @@ static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V) {
238248
239249static Error generateDocForJSON (json::Value &JSON, StringRef Filename,
240250 StringRef Path, raw_fd_ostream &OS,
241- const ClangDocContext &CDCtx) {
251+ const ClangDocContext &CDCtx,
252+ StringRef HTMLRootPath) {
242253 auto StrValue = (*JSON.getAsObject ())[" InfoType" ];
243254 if (StrValue.kind () != json::Value::Kind::String)
244255 return createStringError (" JSON file '%s' does not contain key: 'InfoType'." ,
@@ -249,13 +260,17 @@ static Error generateDocForJSON(json::Value &JSON, StringRef Filename,
249260 " JSON file '%s' does not contain 'InfoType' field as a string." ,
250261 Filename.str ().c_str ());
251262
263+ SmallString<128 > PathVec (Path);
264+ // Remove filename, or else the relative path will have an extra "../"
265+ sys::path::remove_filename (PathVec);
266+ auto RelativeHTMLPath = computeRelativePath (HTMLRootPath, PathVec);
252267 if (ObjTypeStr.value () == " namespace" ) {
253- if (auto Err = setupTemplateValue (CDCtx, JSON))
268+ if (auto Err = setupTemplateValue (CDCtx, JSON, RelativeHTMLPath ))
254269 return Err;
255270 assert (NamespaceTemplate && " NamespaceTemplate is nullptr." );
256271 NamespaceTemplate->render (JSON, OS);
257272 } else if (ObjTypeStr.value () == " record" ) {
258- if (auto Err = setupTemplateValue (CDCtx, JSON))
273+ if (auto Err = setupTemplateValue (CDCtx, JSON, RelativeHTMLPath ))
259274 return Err;
260275 assert (RecordTemplate && " RecordTemplate is nullptr." );
261276 RecordTemplate->render (JSON, OS);
0 commit comments