summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/Logger.h
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2018-07-11 10:35:11 +0000
committerSam McCall <sam.mccall@gmail.com>2018-07-11 10:35:11 +0000
commitbed5885d9e4f3202d06c11974474a49c56fa397f (patch)
tree49820a0a7770c18de12ec8bb7857e8b2c6b88974 /clang-tools-extra/clangd/Logger.h
parenta042fae6e08d22750b529c3ff685f236bae5141f (diff)
downloadbcm5719-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.h65
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:
OpenPOWER on IntegriCloud