Skip to content

Commit 7ff86c0

Browse files
committed
standalone tagfile generation
#feat
1 parent e068292 commit 7ff86c0

File tree

4 files changed

+124
-57
lines changed

4 files changed

+124
-57
lines changed

src/lib/Gen/hbs/HandlebarsGenerator.cpp

Lines changed: 68 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,9 @@
2828
#include <fstream>
2929
#include <sstream>
3030

31-
namespace clang {
32-
namespace mrdocs {
33-
namespace hbs {
31+
namespace clang::mrdocs::hbs {
3432

33+
namespace {
3534
std::function<void(OutputRef&, std::string_view)>
3635
createEscapeFn(HandlebarsGenerator const& gen)
3736
{
@@ -65,15 +64,15 @@ createExecutors(
6564
HandlebarsCorpus
6665
createDomCorpus(
6766
HandlebarsGenerator const& gen,
68-
Corpus const& corpus)
69-
{
67+
Corpus const& corpus) {
7068
return {
7169
corpus,
7270
gen.fileExtension(),
7371
[&gen](HandlebarsCorpus const& c, doc::Node const& n) {
7472
return gen.toString(c, n);
7573
}};
7674
}
75+
} // (anon)
7776

7877
//------------------------------------------------
7978
//
@@ -89,21 +88,10 @@ build(
8988
{
9089
if (!corpus.config->multipage)
9190
{
92-
auto e = Generator::build(outputPath, corpus);
93-
if (e.has_value() && !corpus.config->tagfile.empty())
94-
{
95-
// Generate tagfile if specified
96-
auto const singlePagePath = getSinglePageFullPath(outputPath, fileExtension());
97-
MRDOCS_CHECK_OR(singlePagePath, Unexpected(singlePagePath.error()));
98-
HandlebarsCorpus hbsCorpus = createDomCorpus(*this, corpus);
99-
MRDOCS_TRY(auto tagFileWriter, TagfileWriter::create(
100-
hbsCorpus,
101-
corpus.config->tagfile,
102-
files::getFileName(*singlePagePath)));
103-
tagFileWriter.build();
104-
}
105-
106-
return e;
91+
MRDOCS_TRY(Generator::build(outputPath, corpus));
92+
MRDOCS_CHECK_OR(!corpus.config->tagfile.empty(), {});
93+
MRDOCS_TRY(buildTagfile(corpus.config->tagfile, corpus));
94+
return {};
10795
}
10896

10997
// Create corpus and executors
@@ -117,21 +105,74 @@ build(
117105
// Wait for all executors to finish and check errors
118106
auto errors = ex.wait();
119107
MRDOCS_CHECK_OR(errors.empty(), Unexpected(errors));
120-
121108
report::info("Generated {} pages", visitor.count());
122109

123-
if (! corpus.config->tagfile.empty())
110+
MRDOCS_CHECK_OR(!corpus.config->tagfile.empty(), {});
111+
MRDOCS_TRY(buildTagfile(corpus.config->tagfile, corpus));
112+
return {};
113+
}
114+
115+
Expected<void>
116+
HandlebarsGenerator::
117+
buildTagfile(
118+
std::ostream& os,
119+
Corpus const& corpus) const
120+
{
121+
HandlebarsCorpus domCorpus = createDomCorpus(*this, corpus);
122+
RawOstream raw_os(os);
123+
if (corpus.config->multipage)
124124
{
125125
MRDOCS_TRY(auto tagFileWriter, TagfileWriter::create(
126-
domCorpus,
127-
corpus.config->tagfile,
128-
outputPath));
126+
domCorpus,
127+
raw_os));
128+
tagFileWriter.build();
129+
}
130+
else
131+
{
132+
// Get the name of the single page output file
133+
auto const singlePagePath = getSinglePageFullPath(corpus.config->output, fileExtension());
134+
MRDOCS_CHECK_OR(singlePagePath, Unexpected(singlePagePath.error()));
135+
auto const singlePathFilename = files::getFileName(*singlePagePath);
136+
MRDOCS_TRY(auto tagFileWriter, TagfileWriter::create(
137+
domCorpus,
138+
raw_os,
139+
singlePathFilename));
129140
tagFileWriter.build();
130141
}
131-
132142
return {};
133143
}
134144

145+
Expected<void>
146+
HandlebarsGenerator::
147+
buildTagfile(
148+
std::string_view const fileName,
149+
Corpus const& corpus) const
150+
{
151+
std::string const dir = files::getParentDir(fileName);
152+
MRDOCS_TRY(files::createDirectory(dir));
153+
std::ofstream os;
154+
try
155+
{
156+
os.open(std::string(fileName),
157+
std::ios_base::binary |
158+
std::ios_base::out |
159+
std::ios_base::trunc // | std::ios_base::noreplace
160+
);
161+
}
162+
catch(std::exception const& ex)
163+
{
164+
return Unexpected(formatError("std::ofstream threw \"{}\"", ex.what()));
165+
}
166+
try
167+
{
168+
return buildTagfile(os, corpus);
169+
}
170+
catch(std::exception const& ex)
171+
{
172+
return Unexpected(formatError("buildOne threw \"{}\"", ex.what()));
173+
}
174+
}
175+
135176
Expected<void>
136177
HandlebarsGenerator::
137178
buildOne(
@@ -178,6 +219,4 @@ escape(OutputRef& out, std::string_view str) const
178219
out << str;
179220
}
180221

181-
} // hbs
182-
} // mrdocs
183-
} // clang
222+
} // clang::mrdocs::hbs

src/lib/Gen/hbs/HandlebarsGenerator.hpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ class HandlebarsGenerator
6767
std::ostream& os,
6868
Corpus const& corpus) const override;
6969

70+
/** Build a tagfile for the corpus.
71+
*/
72+
Expected<void>
73+
buildTagfile(
74+
std::ostream& os,
75+
Corpus const& corpus) const;
76+
77+
/** Build a tagfile for the corpus and store the result in a file.
78+
*/
79+
Expected<void>
80+
buildTagfile(
81+
std::string_view fileName,
82+
Corpus const& corpus) const;
83+
7084
/** Convert a Javadoc node to a string.
7185
*/
7286
virtual
@@ -76,7 +90,7 @@ class HandlebarsGenerator
7690
return {};
7791
}
7892

79-
/** Output a escaped string to the output stream.
93+
/** Output an escaped string to the output stream.
8094
*/
8195
virtual
8296
void

src/lib/Lib/TagfileWriter.cpp

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,36 +31,23 @@ namespace mrdocs {
3131
TagfileWriter::
3232
TagfileWriter(
3333
hbs::HandlebarsCorpus const& corpus,
34-
os_ptr os,
34+
llvm::raw_ostream& os,
3535
std::string_view const defaultFilename
3636
) noexcept
3737
: corpus_(corpus)
38-
, os_(std::move(os))
39-
, tags_(*os_)
38+
, os_(os)
39+
, tags_(os)
4040
, defaultFilename_(defaultFilename)
41-
{
42-
tags_.nesting(false);
43-
}
41+
{}
4442

4543
Expected<TagfileWriter>
4644
TagfileWriter::
4745
create(
4846
hbs::HandlebarsCorpus const& corpus,
49-
std::string_view tagfile,
50-
std::string_view defaultFilename)
47+
llvm::raw_ostream& os,
48+
std::string_view defaultFilename)
5149
{
52-
std::error_code ec;
53-
54-
auto os = std::make_unique<llvm::raw_fd_ostream>(
55-
tagfile.data(),
56-
ec,
57-
llvm::sys::fs::OF_None);
58-
59-
if (ec)
60-
{
61-
return Unexpected(formatError("llvm::raw_fd_ostream(\"{}\") failed with error: {}", tagfile, ec.message()));
62-
}
63-
return TagfileWriter(corpus, std::move(os), defaultFilename);
50+
return TagfileWriter(corpus, os, defaultFilename);
6451
}
6552

6653
void
@@ -76,15 +63,15 @@ void
7663
TagfileWriter::
7764
initialize()
7865
{
79-
(*os_) << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
80-
(*os_) << "<tagfile>\n";
66+
os_ << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
67+
os_ << "<tagfile>\n";
8168
}
8269

8370
void
8471
TagfileWriter::
8572
finalize()
8673
{
87-
(*os_) << "</tagfile>\n";
74+
os_ << "</tagfile>\n";
8875
}
8976

9077

src/lib/Lib/TagfileWriter.hpp

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ class TagfileWriter
3434
using os_ptr = std::unique_ptr<llvm::raw_fd_ostream>;
3535

3636
hbs::HandlebarsCorpus const& corpus_;
37-
os_ptr os_;
37+
llvm::raw_ostream& os_;
3838
xml::XMLTags tags_;
3939
std::string defaultFilename_;
4040

4141
TagfileWriter(
4242
hbs::HandlebarsCorpus const& corpus,
43-
os_ptr os,
43+
llvm::raw_ostream& os,
4444
std::string_view defaultFilename) noexcept;
4545

4646
public:
@@ -49,8 +49,13 @@ class TagfileWriter
4949
This static function creates a TagfileWriter instance using the provided
5050
HandlebarsCorpus, tagfile, and default filename.
5151
52+
This overload provides a default filename for symbols. This is useful
53+
when generating a tagfile for single page output, as there's a single
54+
page to reference before the anchors. All symbols are references to
55+
the same file with different anchors.
56+
5257
@param corpus The HandlebarsCorpus to use for the writer.
53-
@param tagfile The name of the tagfile to write to.
58+
@param os The output stream to write the tagfile to.
5459
@param defaultFilename The default filename to use for a symbol if none
5560
is provided. Typically, the relative path to a single page output file.
5661
This parameter is ignored in multipage mode.
@@ -60,9 +65,31 @@ class TagfileWriter
6065
Expected<TagfileWriter>
6166
create(
6267
hbs::HandlebarsCorpus const& corpus,
63-
std::string_view tagfile,
68+
llvm::raw_ostream& os,
6469
std::string_view defaultFilename);
6570

71+
/** Create a TagfileWriter instance without a reference to a default filename.
72+
73+
This static function creates a TagfileWriter instance using the provided
74+
HandlebarsCorpus and tagfile.
75+
76+
This overload provides no default filename for symbols. This is useful
77+
when generating a tagfile for multipage output, as there's no single
78+
page to reference. All symbols are references to other files.
79+
80+
@param corpus The HandlebarsCorpus to use for the writer.
81+
@param os The output stream to write the tagfile to.
82+
@return An Expected object containing the TagfileWriter instance or an error.
83+
*/
84+
static
85+
Expected<TagfileWriter>
86+
create(
87+
hbs::HandlebarsCorpus const& corpus,
88+
llvm::raw_ostream& os)
89+
{
90+
return create(corpus, os, {});
91+
}
92+
6693
/** Build the tagfile.
6794
6895
This function builds the tagfile by initializing the output,

0 commit comments

Comments
 (0)