diff options
author | Sam McCall <sam.mccall@gmail.com> | 2018-07-11 10:35:11 +0000 |
---|---|---|
committer | Sam McCall <sam.mccall@gmail.com> | 2018-07-11 10:35:11 +0000 |
commit | bed5885d9e4f3202d06c11974474a49c56fa397f (patch) | |
tree | 49820a0a7770c18de12ec8bb7857e8b2c6b88974 /clang-tools-extra/clangd/Logger.h | |
parent | a042fae6e08d22750b529c3ff685f236bae5141f (diff) | |
download | bcm5719-llvm-bed5885d9e4f3202d06c11974474a49c56fa397f.tar.gz bcm5719-llvm-bed5885d9e4f3202d06c11974474a49c56fa397f.zip |
[clangd] Upgrade logging facilities with levels and formatv.
Summary:
log() is split into four functions:
- elog()/log()/vlog() have different severity levels, allowing filtering
- dlog() is a lazy macro which uses LLVM_DEBUG - it logs to the logger, but
conditionally based on -debug-only flag and is omitted in release builds
All logging functions use formatv-style format strings now, e.g:
log("Could not resolve URI {0}: {1}", URI, Result.takeError());
Existing log sites have been split between elog/log/vlog by best guess.
This includes a workaround for passing Error to formatv that can be
simplified when D49170 or similar lands.
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D49008
llvm-svn: 336785
Diffstat (limited to 'clang-tools-extra/clangd/Logger.h')
-rw-r--r-- | clang-tools-extra/clangd/Logger.h | 65 |
1 files changed, 59 insertions, 6 deletions
diff --git a/clang-tools-extra/clangd/Logger.h b/clang-tools-extra/clangd/Logger.h index 7811111a2f6..30dd6cc2ad0 100644 --- a/clang-tools-extra/clangd/Logger.h +++ b/clang-tools-extra/clangd/Logger.h @@ -11,24 +11,77 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H #include "llvm/ADT/Twine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FormatVariadic.h" namespace clang { namespace clangd { -/// Main logging function. -/// Logs messages to a global logger, which can be set up by LoggingSesssion. -/// If no logger is registered, writes to llvm::errs(). -void log(const llvm::Twine &Message); - /// Interface to allow custom logging in clangd. class Logger { public: virtual ~Logger() = default; + enum Level { Debug, Verbose, Info, Error }; + static char indicator(Level L) { return "DVIE"[L]; } + /// Implementations of this method must be thread-safe. - virtual void log(const llvm::Twine &Message) = 0; + virtual void log(Level, const llvm::formatv_object_base &Message) = 0; }; +namespace detail { +const char *debugType(const char *Filename); +void log(Logger::Level, const llvm::formatv_object_base &); + +// We often want to consume llvm::Errors by value when passing them to log(). +// This is tricky because the logging infrastructure must mark them as handled. +// When forwarding argument to formatv, we wrap Errors-by-value in this type +// whose destructor handles the cleanup. +// FIXME: simplify after D49170 lands. +struct WrappedError { + llvm::Error E; + WrappedError(WrappedError &&) = default; + ~WrappedError() { consumeError(std::move(E)); } +}; +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const WrappedError &Err) { + return OS << Err.E; +} +template <typename T> T &&wrap(T &&V) { return std::forward<T>(V); } +inline WrappedError wrap(llvm::Error &&V) { return WrappedError{std::move(V)}; } +template <typename... Ts> +void log(Logger::Level L, const char *Fmt, Ts &&... Vals) { + detail::log(L, llvm::formatv(Fmt, detail::wrap(std::forward<Ts>(Vals))...)); +} +} // namespace detail + +// Clangd logging functions write to a global logger set by LoggingSession. +// If no logger is registered, writes to llvm::errs(). +// All accept llvm::formatv()-style arguments, e.g. log("Text={0}", Text). + +// elog() is used for "loud" errors and warnings. +// This level is often visible to users. +template <typename... Ts> void elog(const char *Fmt, Ts &&... Vals) { + detail::log(Logger::Error, Fmt, std::forward<Ts>(Vals)...); +} +// log() is used for information important to understanding a clangd session. +// e.g. the names of LSP messages sent are logged at this level. +// This level could be enabled in production builds to allow later inspection. +template <typename... Ts> void log(const char *Fmt, Ts &&... Vals) { + detail::log(Logger::Info, Fmt, std::forward<Ts>(Vals)...); +} +// vlog() is used for details often needed for debugging clangd sessions. +// This level would typically be enabled for clangd developers. +template <typename... Ts> void vlog(const char *Fmt, Ts &&... Vals) { + detail::log(Logger::Verbose, Fmt, std::forward<Ts>(Vals)...); +} +// dlog only logs if --debug was passed, or --debug_only=Basename. +// This level would be enabled in a targeted way when debugging. +#define dlog(...) \ + DEBUG_WITH_TYPE(::clang::clangd::detail::debugType(__FILE__), \ + ::clang::clangd::detail::log(Logger::Debug, __VA_ARGS__)) + /// Only one LoggingSession can be active at a time. class LoggingSession { public: |