sammccall updated this revision to Diff 154959.
sammccall added a comment.

Add workaround for formatv+error issues.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D49008

Files:
  clangd/ClangdLSPServer.cpp
  clangd/ClangdServer.cpp
  clangd/ClangdUnit.cpp
  clangd/CodeComplete.cpp
  clangd/Compiler.cpp
  clangd/Diagnostics.cpp
  clangd/FileDistance.cpp
  clangd/FindSymbols.cpp
  clangd/GlobalCompilationDatabase.cpp
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Logger.cpp
  clangd/Logger.h
  clangd/Protocol.cpp
  clangd/ProtocolHandlers.cpp
  clangd/SourceCode.cpp
  clangd/TUScheduler.cpp
  clangd/XRefs.cpp
  clangd/index/SymbolCollector.cpp
  clangd/tool/ClangdMain.cpp

Index: clangd/tool/ClangdMain.cpp
===================================================================
--- clangd/tool/ClangdMain.cpp
+++ clangd/tool/ClangdMain.cpp
@@ -98,6 +98,14 @@
     PrettyPrint("pretty", llvm::cl::desc("Pretty-print JSON output"),
                 llvm::cl::init(false));
 
+static llvm::cl::opt<Logger::Level> LogLevel(
+    "log", llvm::cl::desc("Verbosity of log messages written to stderr"),
+    llvm::cl::values(clEnumValN(Logger::Error, "error", "Error messages only"),
+                     clEnumValN(Logger::Info, "info",
+                                "High level execution tracing"),
+                     clEnumValN(Logger::Debug, "verbose", "Low level details")),
+    llvm::cl::init(Logger::Info));
+
 static llvm::cl::opt<bool> Test(
     "lit-test",
     llvm::cl::desc(
@@ -223,7 +231,7 @@
   if (Tracer)
     TracingSession.emplace(*Tracer);
 
-  JSONOutput Out(llvm::outs(), llvm::errs(),
+  JSONOutput Out(llvm::outs(), llvm::errs(), LogLevel,
                  InputMirrorStream ? InputMirrorStream.getPointer() : nullptr,
                  PrettyPrint);
 
Index: clangd/index/SymbolCollector.cpp
===================================================================
--- clangd/index/SymbolCollector.cpp
+++ clangd/index/SymbolCollector.cpp
@@ -52,7 +52,7 @@
   if (std::error_code EC =
           SM.getFileManager().getVirtualFileSystem()->makeAbsolute(
               AbsolutePath))
-    log("Warning: could not make absolute file: " + EC.message());
+    log("Warning: could not make absolute file: {0}", EC.message());
   if (llvm::sys::path::is_absolute(AbsolutePath)) {
     // Handle the symbolic link path case where the current working directory
     // (getCurrentWorkingDirectory) is a symlink./ We always want to the real
@@ -86,8 +86,7 @@
       return U->toString();
     ErrMsg += llvm::toString(U.takeError()) + "\n";
   }
-  log(llvm::Twine("Failed to create an URI for file ") + AbsolutePath + ": " +
-      ErrMsg);
+  log("Failed to create an URI for file {0}: {1}", AbsolutePath, ErrMsg);
   return llvm::None;
 }
 
Index: clangd/XRefs.cpp
===================================================================
--- clangd/XRefs.cpp
+++ clangd/XRefs.cpp
@@ -46,12 +46,12 @@
     return llvm::None;
   auto Uri = URI::parse(Loc.FileURI);
   if (!Uri) {
-    log("Could not parse URI: " + Loc.FileURI);
+    log("Could not parse URI: {0}", Loc.FileURI);
     return llvm::None;
   }
   auto Path = URI::resolve(*Uri, HintPath);
   if (!Path) {
-    log("Could not resolve URI: " + Loc.FileURI);
+    log("Could not resolve URI: {0}", Loc.FileURI);
     return llvm::None;
   }
   Location LSPLoc;
Index: clangd/TUScheduler.cpp
===================================================================
--- clangd/TUScheduler.cpp
+++ clangd/TUScheduler.cpp
@@ -329,14 +329,14 @@
     // Remove the old AST if it's still in cache.
     IdleASTs.take(this);
 
-    log("Updating file " + FileName + " with command [" +
-        Inputs.CompileCommand.Directory + "] " +
+    log("Updating file {0} with command [{1}] {2}", FileName,
+        Inputs.CompileCommand.Directory,
         llvm::join(Inputs.CompileCommand.CommandLine, " "));
     // Rebuild the preamble and the AST.
     std::unique_ptr<CompilerInvocation> Invocation =
         buildCompilerInvocation(Inputs);
     if (!Invocation) {
-      log("Could not build CompilerInvocation for file " + FileName);
+      elog("Could not build CompilerInvocation for file {0}", FileName);
       // Make sure anyone waiting for the preamble gets notified it could not
       // be built.
       PreambleWasBuilt.notify();
@@ -628,8 +628,8 @@
 void TUScheduler::remove(PathRef File) {
   bool Removed = Files.erase(File);
   if (!Removed)
-    log("Trying to remove file from TUScheduler that is not tracked. File:" +
-        File);
+    elog("Trying to remove file from TUScheduler that is not tracked: {0}",
+         File);
 }
 
 void TUScheduler::runWithAST(
Index: clangd/SourceCode.cpp
===================================================================
--- clangd/SourceCode.cpp
+++ clangd/SourceCode.cpp
@@ -192,7 +192,7 @@
     FilePath = F->getName();
   if (!llvm::sys::path::is_absolute(FilePath)) {
     if (!SourceMgr.getFileManager().makeAbsolutePath(FilePath)) {
-      log("Could not turn relative path to absolute: " + FilePath);
+      log("Could not turn relative path to absolute: {0}", FilePath);
       return llvm::None;
     }
   }
Index: clangd/ProtocolHandlers.cpp
===================================================================
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -33,7 +33,7 @@
       if (fromJSON(RawParams, P)) {
         (Callbacks->*Handler)(P);
       } else {
-        log("Failed to decode " + Method + " request.");
+        elog("Failed to decode {0} request.", Method);
       }
     });
   }
Index: clangd/Protocol.cpp
===================================================================
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -34,16 +34,17 @@
   if (auto S = E.getAsString()) {
     auto U = URI::parse(*S);
     if (!U) {
-      log("Failed to parse URI " + *S + ": " + llvm::toString(U.takeError()));
+      elog("Failed to parse URI {0}: {1}", *S, U.takeError());
       return false;
     }
     if (U->scheme() != "file" && U->scheme() != "test") {
-      log("Clangd only supports 'file' URI scheme for workspace files: " + *S);
+      elog("Clangd only supports 'file' URI scheme for workspace files: {0}",
+           *S);
       return false;
     }
     auto Path = URI::resolve(*U);
     if (!Path) {
-      log(llvm::toString(Path.takeError()));
+      log("{0}", Path.takeError());
       return false;
     }
     R = URIForFile(*Path);
Index: clangd/Logger.h
===================================================================
--- clangd/Logger.h
+++ 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:
Index: clangd/Logger.cpp
===================================================================
--- clangd/Logger.cpp
+++ clangd/Logger.cpp
@@ -25,15 +25,24 @@
 
 LoggingSession::~LoggingSession() { L = nullptr; }
 
-void log(const llvm::Twine &Message) {
+void detail::log(Logger::Level Level,
+                 const llvm::formatv_object_base &Message) {
   if (L)
-    L->log(Message);
+    L->log(Level, Message);
   else {
     static std::mutex Mu;
     std::lock_guard<std::mutex> Guard(Mu);
     llvm::errs() << Message << "\n";
   }
 }
 
+const char *detail::debugType(const char *Filename) {
+  if (const char *Slash = strrchr(Filename, '/'))
+    return Slash + 1;
+  if (const char *Backslash = strrchr(Filename, '\\'))
+    return Backslash + 1;
+  return Filename;
+}
+
 } // namespace clangd
 } // namespace clang
Index: clangd/JSONRPCDispatcher.h
===================================================================
--- clangd/JSONRPCDispatcher.h
+++ clangd/JSONRPCDispatcher.h
@@ -30,14 +30,16 @@
   // JSONOutput now that we pass Context everywhere.
 public:
   JSONOutput(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs,
-             llvm::raw_ostream *InputMirror = nullptr, bool Pretty = false)
-      : Pretty(Pretty), Outs(Outs), Logs(Logs), InputMirror(InputMirror) {}
+             Logger::Level MinLevel, llvm::raw_ostream *InputMirror = nullptr,
+             bool Pretty = false)
+      : Pretty(Pretty), MinLevel(MinLevel), Outs(Outs), Logs(Logs),
+        InputMirror(InputMirror) {}
 
   /// Emit a JSONRPC message.
   void writeMessage(const llvm::json::Value &Result);
 
   /// Write a line to the logging stream.
-  void log(const Twine &Message) override;
+  void log(Level, const llvm::formatv_object_base &Message) override;
 
   /// Mirror \p Message into InputMirror stream. Does nothing if InputMirror is
   /// null.
@@ -48,6 +50,7 @@
   const bool Pretty;
 
 private:
+  Logger::Level MinLevel;
   llvm::raw_ostream &Outs;
   llvm::raw_ostream &Logs;
   llvm::raw_ostream *InputMirror;
Index: clangd/JSONRPCDispatcher.cpp
===================================================================
--- clangd/JSONRPCDispatcher.cpp
+++ clangd/JSONRPCDispatcher.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Chrono.h"
 #include "llvm/Support/Errno.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/SourceMgr.h"
 #include <istream>
@@ -68,14 +69,18 @@
     Outs << "Content-Length: " << S.size() << "\r\n\r\n" << S;
     Outs.flush();
   }
-  log(llvm::Twine("--> ") + S + "\n");
+  vlog("--> {0}\n", S);
 }
 
-void JSONOutput::log(const Twine &Message) {
+void JSONOutput::log(Logger::Level Level,
+                     const llvm::formatv_object_base &Message) {
+  if (Level < MinLevel)
+    return;
   llvm::sys::TimePoint<> Timestamp = std::chrono::system_clock::now();
   trace::log(Message);
   std::lock_guard<std::mutex> Guard(StreamMutex);
-  Logs << llvm::formatv("[{0:%H:%M:%S.%L}] {1}\n", Timestamp, Message);
+  Logs << llvm::formatv("{0}[{1:%H:%M:%S.%L}] {2}\n", indicator(Level),
+                        Timestamp, Message);
   Logs.flush();
 }
 
@@ -90,7 +95,7 @@
 void clangd::reply(json::Value &&Result) {
   auto ID = Context::current().get(RequestID);
   if (!ID) {
-    log("Attempted to reply to a notification!");
+    elog("Attempted to reply to a notification!");
     return;
   }
   RequestSpan::attach([&](json::Object &Args) { Args["Reply"] = Result; });
@@ -104,7 +109,7 @@
 }
 
 void clangd::replyError(ErrorCode code, const llvm::StringRef &Message) {
-  log("Error " + Twine(static_cast<int>(code)) + ": " + Message);
+  elog("Error {0}: {1}", static_cast<int>(code), Message);
   RequestSpan::attach([&](json::Object &Args) {
     Args["Error"] = json::Object{{"code", static_cast<int>(code)},
                                  {"message", Message.str()}};
@@ -230,9 +235,9 @@
     // Content-Length is a mandatory header, and the only one we handle.
     if (LineRef.consume_front("Content-Length: ")) {
       if (ContentLength != 0) {
-        log("Warning: Duplicate Content-Length header received. "
-            "The previous value for this message (" +
-            llvm::Twine(ContentLength) + ") was ignored.");
+        elog("Warning: Duplicate Content-Length header received. "
+             "The previous value for this message ({0}) was ignored.",
+             ContentLength);
       }
       llvm::getAsUnsignedInteger(LineRef.trim(), 0, ContentLength);
       continue;
@@ -248,8 +253,9 @@
 
   // The fuzzer likes crashing us by sending "Content-Length: 9999999999999999"
   if (ContentLength > 1 << 30) { // 1024M
-    log("Refusing to read message with long Content-Length: " +
-        Twine(ContentLength) + ". Expect protocol errors.");
+    elog("Refusing to read message with long Content-Length: {0}. "
+         "Expect protocol errors",
+         ContentLength);
     return llvm::None;
   }
   if (ContentLength == 0) {
@@ -264,8 +270,8 @@
                                        ContentLength - Pos, In);
     Out.mirrorInput(StringRef(&JSON[Pos], Read));
     if (Read == 0) {
-      log("Input was aborted. Read only " + llvm::Twine(Pos) +
-          " bytes of expected " + llvm::Twine(ContentLength) + ".");
+      elog("Input was aborted. Read only {0} bytes of expected {1}.", Pos,
+           ContentLength);
       return llvm::None;
     }
     clearerr(In); // If we're done, the error was transient. If we're not done,
@@ -297,7 +303,7 @@
   }
 
   if (ferror(In)) {
-    log("Input error while reading message!");
+    elog("Input error while reading message!");
     return llvm::None;
   } else { // Including EOF
     Out.mirrorInput(
@@ -321,21 +327,20 @@
       (InputStyle == Delimited) ? readDelimitedMessage : readStandardMessage;
   while (!IsDone && !feof(In)) {
     if (ferror(In)) {
-      log("IO error: " + llvm::sys::StrError());
+      elog("IO error: {0}", llvm::sys::StrError());
       return;
     }
     if (auto JSON = ReadMessage(In, Out)) {
       if (auto Doc = json::parse(*JSON)) {
         // Log the formatted message.
-        log(llvm::formatv(Out.Pretty ? "<-- {0:2}\n" : "<-- {0}\n", *Doc));
+        vlog(Out.Pretty ? "<-- {0:2}\n" : "<-- {0}\n", *Doc);
         // Finally, execute the action for this JSON message.
         if (!Dispatcher.call(*Doc, Out))
-          log("JSON dispatch failed!");
+          elog("JSON dispatch failed!");
       } else {
         // Parse error. Log the raw message.
-        log(llvm::formatv("<-- {0}\n" , *JSON));
-        log(llvm::Twine("JSON parse error: ") +
-            llvm::toString(Doc.takeError()));
+        vlog("<-- {0}\n", *JSON);
+        elog("JSON parse error: {0}", llvm::toString(Doc.takeError()));
       }
     }
   }
Index: clangd/GlobalCompilationDatabase.cpp
===================================================================
--- clangd/GlobalCompilationDatabase.cpp
+++ clangd/GlobalCompilationDatabase.cpp
@@ -47,7 +47,7 @@
       return std::move(Candidates.front());
     }
   } else {
-    log("Failed to find compilation database for " + Twine(File));
+    log("Failed to find compilation database for {0}", File);
   }
   return llvm::None;
 }
Index: clangd/FindSymbols.cpp
===================================================================
--- clangd/FindSymbols.cpp
+++ clangd/FindSymbols.cpp
@@ -125,16 +125,15 @@
     auto &CD = Sym.Definition ? Sym.Definition : Sym.CanonicalDeclaration;
     auto Uri = URI::parse(CD.FileURI);
     if (!Uri) {
-      log(llvm::formatv(
-          "Workspace symbol: Could not parse URI '{0}' for symbol '{1}'.",
-          CD.FileURI, Sym.Name));
+      log("Workspace symbol: Could not parse URI '{0}' for symbol '{1}'.",
+          CD.FileURI, Sym.Name);
       return;
     }
     auto Path = URI::resolve(*Uri, HintPath);
     if (!Path) {
-      log(llvm::formatv("Workspace symbol: Could not resolve path for URI "
-                        "'{0}' for symbol '{1}'.",
-                        (*Uri).toString(), Sym.Name.str()));
+      log("Workspace symbol: Could not resolve path for URI '{0}' for symbol "
+          "'{1}'.",
+          Uri->toString(), Sym.Name);
       return;
     }
     Location L;
@@ -158,16 +157,15 @@
     if (auto NameMatch = Filter.match(Sym.Name))
       Relevance.NameMatch = *NameMatch;
     else {
-      log(llvm::formatv("Workspace symbol: {0} didn't match query {1}",
-                        Sym.Name, Filter.pattern()));
+      log("Workspace symbol: {0} didn't match query {1}", Sym.Name,
+          Filter.pattern());
       return;
     }
     Relevance.merge(Sym);
     auto Score =
         evaluateSymbolAndRelevance(Quality.evaluate(), Relevance.evaluate());
-    LLVM_DEBUG(llvm::dbgs() << "FindSymbols: " << Sym.Scope << Sym.Name << " = "
-                            << Score << "\n"
-                            << Quality << Relevance << "\n");
+    dlog("FindSymbols: {0}{1} = {2}\n{3}{4}\n", Sym.Scope, Sym.Name, Score,
+         Quality, Relevance);
 
     Top.push({Score, std::move(Info)});
   });
Index: clangd/FileDistance.cpp
===================================================================
--- clangd/FileDistance.cpp
+++ clangd/FileDistance.cpp
@@ -35,7 +35,6 @@
 #include "Logger.h"
 #include "llvm/ADT/STLExtras.h"
 #include <queue>
-#define DEBUG_TYPE "FileDistance"
 
 namespace clang {
 namespace clangd {
@@ -64,8 +63,8 @@
   // Keep track of down edges, in case we can use them to improve on this.
   for (const auto &S : Sources) {
     auto Canonical = canonicalize(S.getKey());
-    LLVM_DEBUG(dbgs() << "Source " << Canonical << " = " << S.second.Cost
-                      << ", MaxUp=" << S.second.MaxUpTraversals << "\n");
+    dlog("Source {0} = {1}, MaxUp = {2}", Canonical, S.second.Cost,
+         S.second.MaxUpTraversals);
     // Walk up to ancestors of this source, assigning cost.
     StringRef Rest = Canonical;
     llvm::hash_code Hash = hash_value(Rest);
@@ -134,21 +133,19 @@
       Cost += Opts.DownCost;
     Cache.try_emplace(Hash, Cost);
   }
-  LLVM_DEBUG(dbgs() << "distance(" << Path << ") = " << Cost << "\n");
+  dlog("distance({0} = {1})", Path, Cost);
   return Cost;
 }
 
 unsigned URIDistance::distance(llvm::StringRef URI) {
   auto R = Cache.try_emplace(llvm::hash_value(URI), FileDistance::kUnreachable);
   if (!R.second)
     return R.first->getSecond();
   if (auto U = clangd::URI::parse(URI)) {
-    LLVM_DEBUG(dbgs() << "distance(" << URI << ") = distance(" << U->body()
-                      << ")\n");
+    dlog("distance({0} = {1})", URI, U->body());
     R.first->second = forScheme(U->scheme()).distance(U->body());
   } else {
-    log("URIDistance::distance() of unparseable " + URI + ": " +
-        llvm::toString(U.takeError()));
+    log("URIDistance::distance() of unparseable {0}: {1}", URI, U.takeError());
   }
   return R.first->second;
 }
@@ -163,9 +160,8 @@
       else
         consumeError(U.takeError());
     }
-    LLVM_DEBUG(dbgs() << "FileDistance for scheme " << Scheme << ": "
-                      << SchemeSources.size() << "/" << Sources.size()
-                      << " sources\n");
+    dlog("FileDistance for scheme {0}: {1}/{2} sources", Scheme,
+         SchemeSources.size(), Sources.size());
     Delegate.reset(new FileDistance(std::move(SchemeSources), Opts));
   }
   return *Delegate;
Index: clangd/Diagnostics.cpp
===================================================================
--- clangd/Diagnostics.cpp
+++ clangd/Diagnostics.cpp
@@ -375,7 +375,7 @@
   if (mentionsMainFile(*LastDiag))
     Output.push_back(std::move(*LastDiag));
   else
-    log(Twine("Dropped diagnostic outside main file:") + LastDiag->File + ":" +
+    log("Dropped diagnostic outside main file: {0}: {1}", LastDiag->File,
         LastDiag->Message);
   LastDiag.reset();
 }
Index: clangd/Compiler.cpp
===================================================================
--- clangd/Compiler.cpp
+++ clangd/Compiler.cpp
@@ -31,7 +31,7 @@
     OS << ":";
   }
 
-  clangd::log(llvm::formatv("Ignored diagnostic. {0}{1}", Location, Message));
+  clangd::log("Ignored diagnostic. {0}{1}", Location, Message);
 }
 
 void IgnoreDiagnostics::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
Index: clangd/CodeComplete.cpp
===================================================================
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -308,11 +308,10 @@
         if (Include->second)
           Completion.HeaderInsertion = Includes.insert(Include->first);
       } else
-        log(llvm::formatv(
-            "Failed to generate include insertion edits for adding header "
+        log("Failed to generate include insertion edits for adding header "
             "(FileURI='{0}', IncludeHeader='{1}') into {2}",
             C.IndexResult->CanonicalDeclaration.FileURI,
-            C.IndexResult->Detail->IncludeHeader, FileName));
+            C.IndexResult->Detail->IncludeHeader, FileName);
     }
   }
 
@@ -593,11 +592,10 @@
     if (NumResults == 0 && !contextAllowsIndex(Context.getKind()))
       return;
     if (CCSema) {
-      log(llvm::formatv(
-          "Multiple code complete callbacks (parser backtracked?). "
+      log("Multiple code complete callbacks (parser backtracked?). "
           "Dropping results from context {0}, keeping results from {1}.",
           getCompletionKindString(Context.getKind()),
-          getCompletionKindString(this->CCContext.getKind())));
+          getCompletionKindString(this->CCContext.getKind()));
       return;
     }
     // Record the completion context.
@@ -798,7 +796,7 @@
                                           &DummyDiagsConsumer, false),
       Input.VFS);
   if (!CI) {
-    log("Couldn't create CompilerInvocation");
+    elog("Couldn't create CompilerInvocation");
     return false;
   }
   auto &FrontendOpts = CI->getFrontendOpts();
@@ -812,8 +810,7 @@
   FrontendOpts.CodeCompletionAt.FileName = Input.FileName;
   auto Offset = positionToOffset(Input.Contents, Input.Pos);
   if (!Offset) {
-    log("Code completion position was invalid " +
-        llvm::toString(Offset.takeError()));
+    elog("Code completion position was invalid {0}", Offset.takeError());
     return false;
   }
   std::tie(FrontendOpts.CodeCompletionAt.Line,
@@ -836,15 +833,15 @@
 
   SyntaxOnlyAction Action;
   if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
-    log("BeginSourceFile() failed when running codeComplete for " +
+    log("BeginSourceFile() failed when running codeComplete for {0}",
         Input.FileName);
     return false;
   }
   if (Includes)
     Clang->getPreprocessor().addPPCallbacks(
         collectIncludeStructureCallback(Clang->getSourceManager(), Includes));
   if (!Action.Execute()) {
-    log("Execute() failed when running codeComplete for " + Input.FileName);
+    log("Execute() failed when running codeComplete for {0}", Input.FileName);
     return false;
   }
   Action.EndSourceFile();
@@ -965,8 +962,8 @@
                            format::DefaultFallbackStyle, SemaCCInput.Contents,
                            SemaCCInput.VFS.get());
       if (!Style) {
-        log("Failed to get FormatStyle for file" + SemaCCInput.FileName + ": " +
-            llvm::toString(Style.takeError()) + ". Fallback is LLVM style.");
+        log("getStyle() failed for file {0}: {1}. Fallback is LLVM style.",
+            SemaCCInput.FileName, Style.takeError());
         Style = format::getLLVMStyle();
       }
       // If preprocessor was run, inclusions from preprocessor callback should
@@ -1001,10 +998,9 @@
       Inserter.reset(); // Make sure this doesn't out-live Clang.
       SPAN_ATTACH(Tracer, "sema_completion_kind",
                   getCompletionKindString(Recorder->CCContext.getKind()));
-      log(llvm::formatv(
-          "Code complete: sema context {0}, query scopes [{1}]",
+      log("Code complete: sema context {0}, query scopes [{1}]",
           getCompletionKindString(Recorder->CCContext.getKind()),
-          llvm::join(QueryScopes.begin(), QueryScopes.end(), ",")));
+          llvm::join(QueryScopes.begin(), QueryScopes.end(), ","));
     });
 
     Recorder = RecorderOwner.get();
@@ -1016,10 +1012,10 @@
     SPAN_ATTACH(Tracer, "merged_results", NBoth);
     SPAN_ATTACH(Tracer, "returned_results", int64_t(Output.Completions.size()));
     SPAN_ATTACH(Tracer, "incomplete", Output.HasMore);
-    log(llvm::formatv("Code complete: {0} results from Sema, {1} from Index, "
-                      "{2} matched, {3} returned{4}.",
-                      NSema, NIndex, NBoth, Output.Completions.size(),
-                      Output.HasMore ? " (incomplete)" : ""));
+    log("Code complete: {0} results from Sema, {1} from Index, "
+        "{2} matched, {3} returned{4}.",
+        NSema, NIndex, NBoth, Output.Completions.size(),
+        Output.HasMore ? " (incomplete)" : "");
     assert(!Opts.Limit || Output.Completions.size() <= Opts.Limit);
     // We don't assert that isIncomplete means we hit a limit.
     // Indexes may choose to impose their own limits even if we don't have one.
@@ -1068,9 +1064,8 @@
     Req.Scopes = QueryScopes;
     // FIXME: we should send multiple weighted paths here.
     Req.ProximityPaths.push_back(FileName);
-    log(llvm::formatv("Code complete: fuzzyFind(\"{0}\", scopes=[{1}])",
-                      Req.Query,
-                      llvm::join(Req.Scopes.begin(), Req.Scopes.end(), ",")));
+    vlog("Code complete: fuzzyFind(\"{0}\", scopes=[{1}])", Req.Query,
+         llvm::join(Req.Scopes.begin(), Req.Scopes.end(), ","));
     // Run the query against the index.
     if (Opts.Index->fuzzyFind(
             Req, [&](const Symbol &Sym) { ResultsBuilder.insert(Sym); }))
@@ -1178,9 +1173,9 @@
                                ? Scores.Total / Relevance.NameMatch
                                : Scores.Quality;
 
-    LLVM_DEBUG(llvm::dbgs() << "CodeComplete: " << First.Name << " (" << Origin
-                            << ") = " << Scores.Total << "\n"
-                            << Quality << Relevance << "\n");
+    dlog("CodeComplete: {0} ({1}) = {2}\n{3}{4}\n", First.Name,
+         llvm::to_string(Origin), Scores.Total, llvm::to_string(Quality),
+         llvm::to_string(Relevance));
 
     NSema += bool(Origin & SymbolOrigin::AST);
     NIndex += FromIndex;
Index: clangd/ClangdUnit.cpp
===================================================================
--- clangd/ClangdUnit.cpp
+++ clangd/ClangdUnit.cpp
@@ -147,7 +147,7 @@
   auto Action = llvm::make_unique<ClangdFrontendAction>();
   const FrontendInputFile &MainInput = Clang->getFrontendOpts().Inputs[0];
   if (!Action->BeginSourceFile(*Clang, MainInput)) {
-    log("BeginSourceFile() failed when building AST for " +
+    log("BeginSourceFile() failed when building AST for {0}",
         MainInput.getFile());
     return llvm::None;
   }
@@ -159,7 +159,7 @@
       collectIncludeStructureCallback(Clang->getSourceManager(), &Includes));
 
   if (!Action->Execute())
-    log("Execute() failed when building AST for " + MainInput.getFile());
+    log("Execute() failed when building AST for {0}", MainInput.getFile());
 
   // UnitDiagsConsumer is local, we can not store it in CompilerInstance that
   // has a longer lifetime.
@@ -307,11 +307,11 @@
       compileCommandsAreEqual(Inputs.CompileCommand, OldCompileCommand) &&
       OldPreamble->Preamble.CanReuse(CI, ContentsBuffer.get(), Bounds,
                                      Inputs.FS.get())) {
-    log("Reusing preamble for file " + Twine(FileName));
+    vlog("Reusing preamble for file {0}", Twine(FileName));
     return OldPreamble;
   }
-  log("Preamble for file " + Twine(FileName) +
-      " cannot be reused. Attempting to rebuild it.");
+  vlog("Preamble for file {0} cannot be reused. Attempting to rebuild it.",
+       FileName);
 
   trace::Span Tracer("BuildPreamble");
   SPAN_ATTACH(Tracer, "File", FileName);
@@ -343,13 +343,13 @@
   CI.getFrontendOpts().SkipFunctionBodies = false;
 
   if (BuiltPreamble) {
-    log("Built preamble of size " + Twine(BuiltPreamble->getSize()) +
-        " for file " + Twine(FileName));
+    vlog("Built preamble of size {0} for file {1}", BuiltPreamble->getSize(),
+         FileName);
     return std::make_shared<PreambleData>(
         std::move(*BuiltPreamble), PreambleDiagnostics.take(),
         SerializedDeclsCollector.takeIncludes());
   } else {
-    log("Could not build a preamble for file " + Twine(FileName));
+    elog("Could not build a preamble for file {0}", FileName);
     return nullptr;
   }
 }
@@ -379,7 +379,7 @@
   const SourceManager &SourceMgr = AST.getSourceManager();
   auto Offset = positionToOffset(SourceMgr.getBufferData(FID), Pos);
   if (!Offset) {
-    log("getBeginningOfIdentifier: " + toString(Offset.takeError()));
+    log("getBeginningOfIdentifier: {0}", Offset.takeError());
     return SourceLocation();
   }
   SourceLocation InputLoc = SourceMgr.getComposedLoc(FID, *Offset);
Index: clangd/ClangdServer.cpp
===================================================================
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -118,12 +118,12 @@
   auto FS = FSProvider.getFileSystem();
   auto Status = FS->status(RootPath);
   if (!Status)
-    log("Failed to get status for RootPath " + RootPath + ": " +
-        Status.getError().message());
+    elog("Failed to get status for RootPath {0}: {1}", RootPath,
+         Status.getError().message());
   else if (Status->isDirectory())
     this->RootPath = RootPath;
   else
-    log("The provided RootPath " + RootPath + " is not a directory.");
+    elog("The provided RootPath {0} is not a directory.", RootPath);
 }
 
 void ClangdServer::addDocument(PathRef File, StringRef Contents,
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -160,7 +160,7 @@
     DraftMgr.removeDraft(File);
     Server.removeDocument(File);
     CDB.invalidate(File);
-    log(llvm::toString(Contents.takeError()));
+    elog("Failed to update {0}: {1}", File, Contents.takeError());
     return;
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to