Skip to content

Commit d3b29fe

Browse files
committed
refactor Reporter
1 parent 43c1509 commit d3b29fe

File tree

13 files changed

+220
-338
lines changed

13 files changed

+220
-338
lines changed

include/mrdox/Reporter.hpp

Lines changed: 159 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
#define MRDOX_REPORTER_HPP
1414

1515
#include <llvm/Support/Error.h>
16+
#include <llvm/Support/Format.h>
1617
#include <llvm/Support/Mutex.h>
1718
#include <llvm/Support/raw_ostream.h>
1819
#include <cassert>
19-
#include <new>
2020
#include <source_location>
2121
#include <string>
2222
#include <string_view>
@@ -38,74 +38,79 @@ struct Reporter
3838
{
3939
/** Return a suitable exit code.
4040
*/
41-
int
42-
getExitCode() const noexcept
43-
{
44-
if(! failed_)
45-
return EXIT_SUCCESS;
46-
return EXIT_FAILURE;
47-
}
41+
int getExitCode() const noexcept;
42+
43+
/** Print formatted output.
4844
49-
/** Report a non-successful Error
45+
@param arg0, args The values to write.
5046
*/
47+
template<class Arg0, class... Args>
5148
void
52-
failed(llvm::Error&& err);
49+
print(
50+
Arg0&& arg, Args&&... args);
5351

5452
/** Report the failure of an action.
5553
56-
@param action The operation which failed.
57-
@param e The object which holds the error.
58-
@param loc The location where the report is called.
54+
@param arg0, args The values to write.
5955
*/
60-
template<class E>
56+
template<class Arg0, class... Args>
6157
void
6258
failed(
63-
llvm::StringRef action,
64-
E&& e,
65-
std::source_location const& loc =
66-
std::source_location::current())
67-
{
68-
errs(action, " failed: ", std::move(e), " at ", loc);
69-
failed_ = true;
70-
}
59+
Arg0&& arg, Args&&... args);
7160

72-
/** Report a unit test failure.
61+
/** Return true and report a message if an error is indicated.
7362
74-
@par Thread Safety
75-
May be called concurrently.
76-
*/
77-
void
78-
testFailed()
79-
{
80-
failed_ = true;
81-
}
63+
The error object `e` is inspected for a failure
64+
condition. If `e` does not contain a failure,
65+
then this function returns `false`. Otherwise
66+
the function emits a diagnostic message to the
67+
error channel and returns `true`.
8268
83-
/** Write a formatted string to outputs.
69+
@par Output
70+
The diagnostic message will always have the form:
71+
@code
72+
error: couldn't %1 because %2
73+
@endcode
74+
The first string is formed from the `actionFormat`
75+
parameter and the variadic list of arguments,
76+
while the second string is formed from the error
77+
object.
8478
85-
@par Thread Safety
86-
May be called concurrently.
79+
If source location information is available, it
80+
is reported on additional indented lines following
81+
the diagnostic message.
82+
83+
@par Effects
84+
The number of errors seen by the reporter
85+
is incremented by one.
86+
87+
@return true if `e` indicates a failure.
88+
89+
@param e The error object to inspect.
90+
91+
@param arg0, args The values to write.
8792
*/
88-
template<class... Args>
89-
void
90-
outs(Args&&... args) const
91-
{
92-
llvm::StringRef s = format(std::forward<Args>(args)...);
93-
std::lock_guard<llvm::sys::Mutex> lock(m_);
94-
llvm::errs() << s << '\n';
95-
}
93+
template<
94+
class E,
95+
class Arg0, class... Args>
96+
[[nodiscard]]
97+
bool
98+
error(
99+
E&& e,
100+
Arg0&& arg0,
101+
Args&&... args);
96102

97-
/** Write a formatted string to errors.
103+
//--------------------------------------------
104+
105+
/** Report a unit test failure.
98106
99107
@par Thread Safety
100108
May be called concurrently.
101109
*/
102-
template<class... Args>
103110
void
104-
errs(Args&&... args) const
111+
testFailed()
105112
{
106-
llvm::StringRef s = format(std::forward<Args>(args)...);
107-
std::lock_guard<llvm::sys::Mutex> lock(m_);
108-
llvm::errs() << s << '\n';
113+
failed_ = true;
109114
}
110115

111116
static
@@ -114,94 +119,145 @@ struct Reporter
114119
std::source_location const& loc);
115120

116121
private:
117-
/** Return a string formatted from arguments.
122+
//--------------------------------------------
118123

119-
@par Thread Safety
120-
May be called concurrently.
121-
*/
122-
template<class... Args>
123-
llvm::StringRef
124-
format(
125-
Args&&... args) const
124+
template<class T>
125+
static bool isFailure(llvm::Expected<T>& e) noexcept
126126
{
127-
static thread_local std::string temp;
128-
temp.clear();
129-
llvm::raw_string_ostream os(temp);
130-
format_impl(os, std::forward<Args>(args)...);
131-
return llvm::StringRef(temp.data(), temp.size());
127+
return ! e.operator bool();
132128
}
133129

134-
/** Format arguments into an output stream.
135-
*/
136-
template<class Arg0, class... Args>
137-
void
138-
format_impl(
139-
llvm::raw_string_ostream& os,
140-
Arg0&& arg0,
141-
Args&&... args) const
130+
template<class T>
131+
static bool isFailure(llvm::ErrorOr<T>& e) noexcept
142132
{
143-
format_one(os, std::forward<Arg0>(arg0));
144-
if constexpr(sizeof...(args) > 0)
145-
format_impl(os, std::forward<Args>(args)...);
133+
return ! e.operator bool();
134+
}
135+
136+
static bool isFailure(std::error_code const& ec) noexcept
137+
{
138+
return ec.operator bool();
146139
}
147140

148141
template<class T>
149-
void
150-
format_one(
151-
llvm::raw_string_ostream& os,
152-
T const& t) const
142+
auto&& nice(T&& t) const
153143
{
154-
os << t;
144+
return std::forward<T>(t);
155145
}
156146

157-
void
158-
format_one(
159-
llvm::raw_string_ostream& os,
160-
std::error_code const& ec) const
147+
template<class T>
148+
auto nice(llvm::Expected<T>& e) const
161149
{
162-
os << ec.message();
150+
return nice(e.takeError());
163151
}
164152

165-
void
166-
format_one(
167-
llvm::raw_string_ostream& os,
168-
llvm::Error&& err) const
153+
template<class T>
154+
auto nice(llvm::Expected<T>&& e) const
169155
{
170-
//err.operator bool(); // VFALCO?
171-
os << toString(std::move(err));
156+
return nice(e.takeError());
172157
}
173158

174159
template<class T>
175-
void
176-
format_one(
177-
llvm::raw_string_ostream& os,
178-
llvm::Expected<T>&& ex) const
160+
auto nice(llvm::ErrorOr<T>& e) const
179161
{
180-
format_one(os, ex.takeError());
162+
return nice(e.takeError());
181163
}
182164

183165
template<class T>
184-
void
185-
format_one(
186-
llvm::raw_string_ostream& os,
187-
llvm::ErrorOr<T>&& eor) const
166+
auto nice(llvm::ErrorOr<T>&& e) const
188167
{
189-
format_one(os, eor.getError());
168+
return nice(e.getError());
190169
}
191170

192-
void
193-
format_one(
194-
llvm::raw_string_ostream& os,
195-
std::source_location const& loc) const
171+
auto nice(std::error_code&& ec) const
196172
{
197-
os << makeString(loc);
173+
return ec.message();
198174
}
199175

176+
auto nice(std::error_code const& ec) const
177+
{
178+
return ec.message();
179+
}
180+
181+
void
182+
threadSafePrint(
183+
llvm::raw_fd_ostream& os,
184+
llvm::StringRef s,
185+
std::size_t* n = nullptr);
186+
187+
static std::string& temp_string();
188+
200189
private:
201190
llvm::sys::Mutex mutable m_;
191+
std::size_t errorCount_ = 0;
202192
bool failed_ = false;
203193
};
204194

195+
//------------------------------------------------
196+
197+
template<
198+
class Arg0, class... Args>
199+
void
200+
Reporter::
201+
print(
202+
Arg0&& arg,
203+
Args&&... args)
204+
{
205+
auto& temp = temp_string();
206+
temp.clear();
207+
{
208+
llvm::raw_string_ostream os(temp);
209+
os << std::forward<Arg0>(arg);
210+
(os << ... << nice(std::forward<Args>(args)));
211+
}
212+
threadSafePrint(llvm::outs(), temp, nullptr);
213+
}
214+
215+
template<
216+
class Arg0, class... Args>
217+
void
218+
Reporter::
219+
failed(
220+
Arg0&& arg,
221+
Args&&... args)
222+
{
223+
auto& temp = temp_string();
224+
temp.clear();
225+
{
226+
llvm::raw_string_ostream os(temp);
227+
os << "error: Couldn't ";
228+
os << std::forward<Arg0>(arg);
229+
(os << ... << nice(std::forward<Args>(args)));
230+
os << ".";
231+
}
232+
threadSafePrint(llvm::errs(), temp, &errorCount_);
233+
}
234+
235+
template<
236+
class E,
237+
class Arg0, class... Args>
238+
bool
239+
Reporter::
240+
error(
241+
E&& e,
242+
Arg0&& arg,
243+
Args&&... args)
244+
{
245+
if(! isFailure(e))
246+
return false;
247+
auto& temp = temp_string();
248+
temp.clear();
249+
{
250+
llvm::raw_string_ostream os(temp);
251+
os << "error: Couldn't ";
252+
os << std::forward<Arg0>(arg);
253+
(os << ... << nice(std::forward<Args>(args)));
254+
os << " because " <<
255+
nice(std::move(e)) << '.';
256+
}
257+
threadSafePrint(llvm::errs(), temp, &errorCount_);
258+
return true;
259+
}
260+
205261
} // mrdox
206262
} // clang
207263

source/lib/Asciidoc.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,8 @@ buildOne(
9393
fs::CD_CreateAlways,
9494
fs::FA_Write,
9595
fs::OF_None);
96-
if(ec)
97-
{
98-
R.failed("llvm::raw_fd_ostream", ec);
96+
if(R.error(ec, "open the stream for '", fileName, "'"))
9997
return false;
100-
}
10198

10299
if(! corpus.canonicalize(R))
103100
return false;

source/lib/Config.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,12 @@ loadFromFile(
100100

101101
// Read the YAML file and apply to this
102102
auto fileText = llvm::MemoryBuffer::getFile(configPath);
103-
if(! fileText)
104-
{
105-
R.failed("llvm::MemoryBuffer::getFile", fileText);
103+
if(R.error(fileText, "read the file '", configPath, "'"))
106104
return false;
107-
}
108105
llvm::yaml::Input yin(**fileText);
109106
yin >> *this;
110-
std::error_code ec = yin.error();
111-
if(ec)
112-
{
113-
R.failed("llvm::yaml::Input::operator>>", ec);
107+
if(R.error(yin.error(), "parse the YAML file"))
114108
return false;
115-
}
116109

117110
// change configPath to the directory
118111
path::remove_filename(configPath);

0 commit comments

Comments
 (0)