ilya-biryukov updated this revision to Diff 115818.
ilya-biryukov added a comment.

- Replaced JSONOutput in Protocol.h/Protocol.cpp with Logger.


https://reviews.llvm.org/D37972

Files:
  clangd/CMakeLists.txt
  clangd/ClangdLSPServer.cpp
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/ClangdUnit.cpp
  clangd/ClangdUnit.h
  clangd/ClangdUnitStore.cpp
  clangd/ClangdUnitStore.h
  clangd/GlobalCompilationDatabase.cpp
  clangd/GlobalCompilationDatabase.h
  clangd/JSONRPCDispatcher.h
  clangd/Logger.cpp
  clangd/Logger.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  unittests/clangd/ClangdTests.cpp

Index: unittests/clangd/ClangdTests.cpp
===================================================================
--- unittests/clangd/ClangdTests.cpp
+++ unittests/clangd/ClangdTests.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "ClangdServer.h"
+#include "Logger.h"
 #include "clang/Basic/VirtualFileSystem.h"
 #include "clang/Config/config.h"
 #include "llvm/ADT/SmallVector.h"
@@ -302,7 +303,8 @@
     ErrorCheckingDiagConsumer DiagConsumer;
     MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
     ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
-                        /*SnippetCompletions=*/false);
+                        /*SnippetCompletions=*/false,
+                        EmptyLogger::getInstance());
     for (const auto &FileWithContents : ExtraFiles)
       FS.Files[getVirtualTestFilePath(FileWithContents.first)] =
           FileWithContents.second;
@@ -365,7 +367,7 @@
   ErrorCheckingDiagConsumer DiagConsumer;
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
   ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
-                      /*SnippetCompletions=*/false);
+                      /*SnippetCompletions=*/false, EmptyLogger::getInstance());
 
   const auto SourceContents = R"cpp(
 #include "foo.h"
@@ -410,7 +412,7 @@
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
 
   ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
-                      /*SnippetCompletions=*/false);
+                      /*SnippetCompletions=*/false, EmptyLogger::getInstance());
 
   const auto SourceContents = R"cpp(
 #include "foo.h"
@@ -457,7 +459,8 @@
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
   // Run ClangdServer synchronously.
   ClangdServer Server(CDB, DiagConsumer, FS,
-                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false);
+                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false,
+                      EmptyLogger::getInstance());
 
   auto FooCpp = getVirtualTestFilePath("foo.cpp");
   const auto SourceContents = "int a;";
@@ -490,7 +493,8 @@
                               "-stdlib=libstdc++"});
   // Run ClangdServer synchronously.
   ClangdServer Server(CDB, DiagConsumer, FS,
-                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false);
+                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false,
+                      EmptyLogger::getInstance());
 
   // Just a random gcc version string
   SmallString<8> Version("4.9.3");
@@ -538,7 +542,8 @@
   ErrorCheckingDiagConsumer DiagConsumer;
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
   ClangdServer Server(CDB, DiagConsumer, FS,
-                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false);
+                      /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false,
+                      EmptyLogger::getInstance());
   // No need to sync reparses, because reparses are performed on the calling
   // thread to true.
 
@@ -597,7 +602,7 @@
   MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
 
   ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
-                      /*SnippetCompletions=*/false);
+                      /*SnippetCompletions=*/false, EmptyLogger::getInstance());
 
   auto FooCpp = getVirtualTestFilePath("foo.cpp");
   const auto SourceContents = R"cpp(
@@ -745,7 +750,8 @@
   {
     MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
     ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
-                        /*SnippetCompletions=*/false);
+                        /*SnippetCompletions=*/false,
+                        EmptyLogger::getInstance());
 
     // Prepare some random distributions for the test.
     std::random_device RandGen;
Index: clangd/Protocol.h
===================================================================
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -29,7 +29,7 @@
 namespace clang {
 namespace clangd {
 
-class JSONOutput;
+class Logger;
 
 struct URI {
   std::string uri;
@@ -59,7 +59,7 @@
   URI uri;
 
   static llvm::Optional<TextDocumentIdentifier>
-  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct Position {
@@ -79,7 +79,7 @@
   }
 
   static llvm::Optional<Position> parse(llvm::yaml::MappingNode *Params,
-                                        JSONOutput &Output);
+                                        clangd::Logger &Logger);
   static std::string unparse(const Position &P);
 };
 
@@ -98,7 +98,7 @@
   }
 
   static llvm::Optional<Range> parse(llvm::yaml::MappingNode *Params,
-                                     JSONOutput &Output);
+                                     clangd::Logger &Logger);
   static std::string unparse(const Range &P);
 };
 
@@ -126,7 +126,7 @@
   std::vector<std::string> extraFlags;
 
   static llvm::Optional<Metadata> parse(llvm::yaml::MappingNode *Params,
-                                        JSONOutput &Output);
+                                        clangd::Logger &Logger);
 };
 
 struct TextEdit {
@@ -139,7 +139,7 @@
   std::string newText;
 
   static llvm::Optional<TextEdit> parse(llvm::yaml::MappingNode *Params,
-                                        JSONOutput &Output);
+                                        clangd::Logger &Logger);
   static std::string unparse(const TextEdit &P);
 };
 
@@ -157,7 +157,7 @@
   std::string text;
 
   static llvm::Optional<TextDocumentItem> parse(llvm::yaml::MappingNode *Params,
-                                                JSONOutput &Output);
+                                                clangd::Logger &Logger);
 };
 
 struct DidOpenTextDocumentParams {
@@ -168,23 +168,23 @@
   llvm::Optional<Metadata> metadata;
 
   static llvm::Optional<DidOpenTextDocumentParams>
-  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct DidCloseTextDocumentParams {
   /// The document that was closed.
   TextDocumentIdentifier textDocument;
 
   static llvm::Optional<DidCloseTextDocumentParams>
-  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct TextDocumentContentChangeEvent {
   /// The new text of the document.
   std::string text;
 
   static llvm::Optional<TextDocumentContentChangeEvent>
-  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct DidChangeTextDocumentParams {
@@ -197,7 +197,7 @@
   std::vector<TextDocumentContentChangeEvent> contentChanges;
 
   static llvm::Optional<DidChangeTextDocumentParams>
-  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct FormattingOptions {
@@ -208,7 +208,7 @@
   bool insertSpaces;
 
   static llvm::Optional<FormattingOptions>
-  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
   static std::string unparse(const FormattingOptions &P);
 };
 
@@ -223,7 +223,7 @@
   FormattingOptions options;
 
   static llvm::Optional<DocumentRangeFormattingParams>
-  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct DocumentOnTypeFormattingParams {
@@ -240,7 +240,7 @@
   FormattingOptions options;
 
   static llvm::Optional<DocumentOnTypeFormattingParams>
-  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct DocumentFormattingParams {
@@ -251,7 +251,7 @@
   FormattingOptions options;
 
   static llvm::Optional<DocumentFormattingParams>
-  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct Diagnostic {
@@ -284,15 +284,15 @@
   }
 
   static llvm::Optional<Diagnostic> parse(llvm::yaml::MappingNode *Params,
-                                          JSONOutput &Output);
+                                          clangd::Logger &Logger);
 };
 
 struct CodeActionContext {
   /// An array of diagnostics.
   std::vector<Diagnostic> diagnostics;
 
   static llvm::Optional<CodeActionContext>
-  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 struct CodeActionParams {
@@ -306,7 +306,7 @@
   CodeActionContext context;
 
   static llvm::Optional<CodeActionParams> parse(llvm::yaml::MappingNode *Params,
-                                                JSONOutput &Output);
+                                                clangd::Logger &Logger);
 };
 
 struct TextDocumentPositionParams {
@@ -317,7 +317,7 @@
   Position position;
 
   static llvm::Optional<TextDocumentPositionParams>
-  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
 /// The kind of a completion entry.
Index: clangd/Protocol.cpp
===================================================================
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -13,19 +13,21 @@
 //===----------------------------------------------------------------------===//
 
 #include "Protocol.h"
-#include "JSONRPCDispatcher.h"
+#include "Logger.h"
 
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
 using namespace clang::clangd;
 
 namespace {
-void logIgnoredField(llvm::StringRef KeyValue, JSONOutput &Output) {
-  Output.log(llvm::formatv("Ignored unknown field \"{0}\"\n", KeyValue));
+void logIgnoredField(llvm::StringRef KeyValue, clangd::Logger &Logger) {
+  Logger.log(llvm::formatv("Ignored unknown field \"{0}\"\n", KeyValue));
 }
 } // namespace
 
@@ -65,7 +67,7 @@
 
 llvm::Optional<TextDocumentIdentifier>
 TextDocumentIdentifier::parse(llvm::yaml::MappingNode *Params,
-                              JSONOutput &Output) {
+                              clangd::Logger &Logger) {
   TextDocumentIdentifier Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -84,14 +86,14 @@
     } else if (KeyValue == "version") {
       // FIXME: parse version, but only for VersionedTextDocumentIdentifiers.
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<Position> Position::parse(llvm::yaml::MappingNode *Params,
-                                         JSONOutput &Output) {
+                                         clangd::Logger &Logger) {
   Position Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -117,7 +119,7 @@
         return llvm::None;
       Result.character = Val;
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
@@ -131,7 +133,7 @@
 }
 
 llvm::Optional<Range> Range::parse(llvm::yaml::MappingNode *Params,
-                                   JSONOutput &Output) {
+                                   clangd::Logger &Logger) {
   Range Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -147,17 +149,17 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "start") {
-      auto Parsed = Position::parse(Value, Output);
+      auto Parsed = Position::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.start = std::move(*Parsed);
     } else if (KeyValue == "end") {
-      auto Parsed = Position::parse(Value, Output);
+      auto Parsed = Position::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.end = std::move(*Parsed);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
@@ -180,7 +182,7 @@
 }
 
 llvm::Optional<TextDocumentItem>
-TextDocumentItem::parse(llvm::yaml::MappingNode *Params, JSONOutput &Output) {
+TextDocumentItem::parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger) {
   TextDocumentItem Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -207,14 +209,14 @@
     } else if (KeyValue == "text") {
       Result.text = Value->getValue(Storage);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<Metadata> Metadata::parse(llvm::yaml::MappingNode *Params,
-                                         JSONOutput &Output) {
+                                         clangd::Logger &Logger) {
   Metadata Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -237,14 +239,14 @@
         Result.extraFlags.push_back(Node->getValue(Storage));
       }
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<TextEdit> TextEdit::parse(llvm::yaml::MappingNode *Params,
-                                         JSONOutput &Output) {
+                                         clangd::Logger &Logger) {
   TextEdit Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -260,7 +262,7 @@
       auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
       if (!Map)
         return llvm::None;
-      auto Parsed = Range::parse(Map, Output);
+      auto Parsed = Range::parse(Map, Logger);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
@@ -270,7 +272,7 @@
         return llvm::None;
       Result.newText = Node->getValue(Storage);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
@@ -286,7 +288,7 @@
 
 llvm::Optional<DidOpenTextDocumentParams>
 DidOpenTextDocumentParams::parse(llvm::yaml::MappingNode *Params,
-                                 JSONOutput &Output) {
+                                 clangd::Logger &Logger) {
   DidOpenTextDocumentParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -302,25 +304,25 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentItem::parse(Value, Output);
+      auto Parsed = TextDocumentItem::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "metadata") {
-      auto Parsed = Metadata::parse(Value, Output);
+      auto Parsed = Metadata::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.metadata = std::move(*Parsed);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<DidCloseTextDocumentParams>
 DidCloseTextDocumentParams::parse(llvm::yaml::MappingNode *Params,
-                                  JSONOutput &Output) {
+                                  clangd::Logger &Logger) {
   DidCloseTextDocumentParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -335,20 +337,20 @@
       auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
       if (!Map)
         return llvm::None;
-      auto Parsed = TextDocumentIdentifier::parse(Map, Output);
+      auto Parsed = TextDocumentIdentifier::parse(Map, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<DidChangeTextDocumentParams>
 DidChangeTextDocumentParams::parse(llvm::yaml::MappingNode *Params,
-                                   JSONOutput &Output) {
+                                   clangd::Logger &Logger) {
   DidChangeTextDocumentParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -364,7 +366,7 @@
       auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
       if (!Map)
         return llvm::None;
-      auto Parsed = TextDocumentIdentifier::parse(Map, Output);
+      auto Parsed = TextDocumentIdentifier::parse(Map, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
@@ -376,21 +378,21 @@
         auto *I = dyn_cast<llvm::yaml::MappingNode>(&Item);
         if (!I)
           return llvm::None;
-        auto Parsed = TextDocumentContentChangeEvent::parse(I, Output);
+        auto Parsed = TextDocumentContentChangeEvent::parse(I, Logger);
         if (!Parsed)
           return llvm::None;
         Result.contentChanges.push_back(std::move(*Parsed));
       }
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<TextDocumentContentChangeEvent>
 TextDocumentContentChangeEvent::parse(llvm::yaml::MappingNode *Params,
-                                      JSONOutput &Output) {
+                                      clangd::Logger &Logger) {
   TextDocumentContentChangeEvent Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -408,14 +410,14 @@
     if (KeyValue == "text") {
       Result.text = Value->getValue(Storage);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<FormattingOptions>
-FormattingOptions::parse(llvm::yaml::MappingNode *Params, JSONOutput &Output) {
+FormattingOptions::parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger) {
   FormattingOptions Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -448,7 +450,7 @@
       }
       Result.insertSpaces = Val;
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
@@ -463,7 +465,7 @@
 
 llvm::Optional<DocumentRangeFormattingParams>
 DocumentRangeFormattingParams::parse(llvm::yaml::MappingNode *Params,
-                                     JSONOutput &Output) {
+                                     clangd::Logger &Logger) {
   DocumentRangeFormattingParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -479,30 +481,30 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value, Output);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "range") {
-      auto Parsed = Range::parse(Value, Output);
+      auto Parsed = Range::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
     } else if (KeyValue == "options") {
-      auto Parsed = FormattingOptions::parse(Value, Output);
+      auto Parsed = FormattingOptions::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.options = std::move(*Parsed);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<DocumentOnTypeFormattingParams>
 DocumentOnTypeFormattingParams::parse(llvm::yaml::MappingNode *Params,
-                                      JSONOutput &Output) {
+                                      clangd::Logger &Logger) {
   DocumentOnTypeFormattingParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -527,30 +529,30 @@
     if (!Value)
       return llvm::None;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value, Output);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "position") {
-      auto Parsed = Position::parse(Value, Output);
+      auto Parsed = Position::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.position = std::move(*Parsed);
     } else if (KeyValue == "options") {
-      auto Parsed = FormattingOptions::parse(Value, Output);
+      auto Parsed = FormattingOptions::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.options = std::move(*Parsed);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<DocumentFormattingParams>
 DocumentFormattingParams::parse(llvm::yaml::MappingNode *Params,
-                                JSONOutput &Output) {
+                                clangd::Logger &Logger) {
   DocumentFormattingParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -566,24 +568,24 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value, Output);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "options") {
-      auto Parsed = FormattingOptions::parse(Value, Output);
+      auto Parsed = FormattingOptions::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.options = std::move(*Parsed);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<Diagnostic> Diagnostic::parse(llvm::yaml::MappingNode *Params,
-                                             JSONOutput &Output) {
+                                             clangd::Logger &Logger) {
   Diagnostic Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -599,7 +601,7 @@
           dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
       if (!Value)
         return llvm::None;
-      auto Parsed = Range::parse(Value, Output);
+      auto Parsed = Range::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
@@ -623,14 +625,14 @@
         return llvm::None;
       Result.message = Value->getValue(Storage);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<CodeActionContext>
-CodeActionContext::parse(llvm::yaml::MappingNode *Params, JSONOutput &Output) {
+CodeActionContext::parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger) {
   CodeActionContext Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -650,20 +652,20 @@
         auto *I = dyn_cast<llvm::yaml::MappingNode>(&Item);
         if (!I)
           return llvm::None;
-        auto Parsed = Diagnostic::parse(I, Output);
+        auto Parsed = Diagnostic::parse(I, Logger);
         if (!Parsed)
           return llvm::None;
         Result.diagnostics.push_back(std::move(*Parsed));
       }
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<CodeActionParams>
-CodeActionParams::parse(llvm::yaml::MappingNode *Params, JSONOutput &Output) {
+CodeActionParams::parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger) {
   CodeActionParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -679,30 +681,30 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value, Output);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "range") {
-      auto Parsed = Range::parse(Value, Output);
+      auto Parsed = Range::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
     } else if (KeyValue == "context") {
-      auto Parsed = CodeActionContext::parse(Value, Output);
+      auto Parsed = CodeActionContext::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.context = std::move(*Parsed);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
 }
 
 llvm::Optional<TextDocumentPositionParams>
 TextDocumentPositionParams::parse(llvm::yaml::MappingNode *Params,
-                                  JSONOutput &Output) {
+                                  clangd::Logger &Logger) {
   TextDocumentPositionParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -718,17 +720,17 @@
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value, Output);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "position") {
-      auto Parsed = Position::parse(Value, Output);
+      auto Parsed = Position::parse(Value, Logger);
       if (!Parsed)
         return llvm::None;
       Result.position = std::move(*Parsed);
     } else {
-      logIgnoredField(KeyValue, Output);
+      logIgnoredField(KeyValue, Logger);
     }
   }
   return Result;
Index: clangd/Logger.h
===================================================================
--- /dev/null
+++ clangd/Logger.h
@@ -0,0 +1,41 @@
+//===--- Logger.h - Logger interface for clangd ------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H
+
+#include "llvm/ADT/Twine.h"
+
+namespace clang {
+namespace clangd {
+
+/// Interface to allow custom logging in clangd.
+class Logger {
+public:
+  virtual ~Logger() = default;
+
+  /// Implementations of this method must be thread-safe.
+  virtual void log(const llvm::Twine &Message) = 0;
+};
+
+/// Logger implementation that ignores all messages.
+class EmptyLogger : public Logger {
+public:
+  static EmptyLogger &getInstance();
+
+  void log(const llvm::Twine &Message) override;
+
+private:
+  EmptyLogger() = default;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
Index: clangd/Logger.cpp
===================================================================
--- /dev/null
+++ clangd/Logger.cpp
@@ -0,0 +1,19 @@
+//===--- Logger.cpp - Logger interface for clangd -------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Logger.h"
+
+using namespace clang::clangd;
+
+EmptyLogger &EmptyLogger::getInstance() {
+  static EmptyLogger Logger;
+  return Logger;
+}
+
+void EmptyLogger::log(const llvm::Twine &Message) {}
Index: clangd/JSONRPCDispatcher.h
===================================================================
--- clangd/JSONRPCDispatcher.h
+++ clangd/JSONRPCDispatcher.h
@@ -10,6 +10,7 @@
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
 
+#include "Logger.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/YAMLParser.h"
@@ -21,16 +22,16 @@
 
 /// Encapsulates output and logs streams and provides thread-safe access to
 /// them.
-class JSONOutput {
+class JSONOutput : public Logger {
 public:
   JSONOutput(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs)
       : Outs(Outs), Logs(Logs) {}
 
   /// Emit a JSONRPC message.
   void writeMessage(const Twine &Message);
 
   /// Write to the logging stream.
-  void log(const Twine &Message);
+  void log(const Twine &Message) override;
 
 private:
   llvm::raw_ostream &Outs;
Index: clangd/GlobalCompilationDatabase.h
===================================================================
--- clangd/GlobalCompilationDatabase.h
+++ clangd/GlobalCompilationDatabase.h
@@ -25,6 +25,8 @@
 
 namespace clangd {
 
+class Logger;
+
 /// Returns a default compile command to use for \p File.
 tooling::CompileCommand getDefaultCompileCommand(PathRef File);
 
@@ -45,6 +47,8 @@
 class DirectoryBasedGlobalCompilationDatabase
     : public GlobalCompilationDatabase {
 public:
+  DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger);
+
   std::vector<tooling::CompileCommand>
   getCompileCommands(PathRef File) override;
 
@@ -61,6 +65,8 @@
 
   /// Stores extra flags per file.
   llvm::StringMap<std::vector<std::string>> ExtraFlagsForFile;
+  /// Used for logging.
+  clangd::Logger &Logger;
 };
 } // namespace clangd
 } // namespace clang
Index: clangd/GlobalCompilationDatabase.cpp
===================================================================
--- clangd/GlobalCompilationDatabase.cpp
+++ clangd/GlobalCompilationDatabase.cpp
@@ -11,6 +11,7 @@
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
+#include "Logger.h"
 
 namespace clang {
 namespace clangd {
@@ -36,6 +37,10 @@
                                  /*Output=*/"");
 }
 
+DirectoryBasedGlobalCompilationDatabase::
+    DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger)
+    : Logger(Logger) {}
+
 std::vector<tooling::CompileCommand>
 DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) {
   std::vector<tooling::CompileCommand> Commands;
@@ -77,26 +82,19 @@
     auto CachedIt = CompilationDatabases.find(Path);
     if (CachedIt != CompilationDatabases.end())
       return CachedIt->second.get();
+
     std::string Error;
     auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error);
-    if (!CDB) {
-      if (!Error.empty()) {
-        // FIXME(ibiryukov): logging
-        // Output.log("Error when trying to load compilation database from " +
-        //            Twine(Path) + ": " + Twine(Error) + "\n");
-      }
+    if (!CDB)
       continue;
-    }
 
     // FIXME(ibiryukov): Invalidate cached compilation databases on changes
-    auto result = CDB.get();
+    auto Result = CDB.get();
     CompilationDatabases.insert(std::make_pair(Path, std::move(CDB)));
-    return result;
+    return Result;
   }
 
-  // FIXME(ibiryukov): logging
-  // Output.log("Failed to find compilation database for " + Twine(File) +
-  // "\n");
+  Logger.log("Failed to find compilation database for " + Twine(File) + "\n");
   return nullptr;
 }
 
Index: clangd/ClangdUnitStore.h
===================================================================
--- clangd/ClangdUnitStore.h
+++ clangd/ClangdUnitStore.h
@@ -20,23 +20,24 @@
 namespace clang {
 namespace clangd {
 
+class Logger;
+
 /// Thread-safe mapping from FileNames to CppFile.
 class CppFileCollection {
 public:
-  std::shared_ptr<CppFile>
-  getOrCreateFile(PathRef File, PathRef ResourceDir,
-                  GlobalCompilationDatabase &CDB,
-                  std::shared_ptr<PCHContainerOperations> PCHs,
-                  IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+  std::shared_ptr<CppFile> getOrCreateFile(
+      PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB,
+      std::shared_ptr<PCHContainerOperations> PCHs,
+      IntrusiveRefCntPtr<vfs::FileSystem> VFS, clangd::Logger &Logger) {
     std::lock_guard<std::mutex> Lock(Mutex);
 
     auto It = OpenedFiles.find(File);
     if (It == OpenedFiles.end()) {
       auto Command = getCompileCommand(CDB, File, ResourceDir);
 
       It = OpenedFiles
                .try_emplace(File, CppFile::Create(File, std::move(Command),
-                                                  std::move(PCHs)))
+                                                  std::move(PCHs), Logger))
                .first;
     }
     return It->second;
@@ -59,7 +60,7 @@
   RecreateResult recreateFileIfCompileCommandChanged(
       PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB,
       std::shared_ptr<PCHContainerOperations> PCHs,
-      IntrusiveRefCntPtr<vfs::FileSystem> VFS);
+      IntrusiveRefCntPtr<vfs::FileSystem> VFS, clangd::Logger &Logger);
 
   std::shared_ptr<CppFile> getFile(PathRef File) {
     std::lock_guard<std::mutex> Lock(Mutex);
Index: clangd/ClangdUnitStore.cpp
===================================================================
--- clangd/ClangdUnitStore.cpp
+++ clangd/ClangdUnitStore.cpp
@@ -30,7 +30,7 @@
 CppFileCollection::recreateFileIfCompileCommandChanged(
     PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB,
     std::shared_ptr<PCHContainerOperations> PCHs,
-    IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+    IntrusiveRefCntPtr<vfs::FileSystem> VFS, clangd::Logger &Logger) {
   auto NewCommand = getCompileCommand(CDB, File, ResourceDir);
 
   std::lock_guard<std::mutex> Lock(Mutex);
@@ -41,12 +41,13 @@
   if (It == OpenedFiles.end()) {
     It = OpenedFiles
              .try_emplace(File, CppFile::Create(File, std::move(NewCommand),
-                                                std::move(PCHs)))
+                                                std::move(PCHs), Logger))
              .first;
   } else if (!compileCommandsAreEqual(It->second->getCompileCommand(),
                                       NewCommand)) {
     Result.RemovedFile = std::move(It->second);
-    It->second = CppFile::Create(File, std::move(NewCommand), std::move(PCHs));
+    It->second =
+        CppFile::Create(File, std::move(NewCommand), std::move(PCHs), Logger);
   }
   Result.FileInCollection = It->second;
   return Result;
Index: clangd/ClangdUnit.h
===================================================================
--- clangd/ClangdUnit.h
+++ clangd/ClangdUnit.h
@@ -40,6 +40,8 @@
 
 namespace clangd {
 
+class Logger;
+
 /// A diagnostic with its FixIts.
 struct DiagWithFixIts {
   clangd::Diagnostic Diag;
@@ -57,7 +59,7 @@
         ArrayRef<serialization::DeclID> PreambleDeclIDs,
         std::unique_ptr<llvm::MemoryBuffer> Buffer,
         std::shared_ptr<PCHContainerOperations> PCHs,
-        IntrusiveRefCntPtr<vfs::FileSystem> VFS);
+        IntrusiveRefCntPtr<vfs::FileSystem> VFS, clangd::Logger &Logger);
 
   ParsedAST(ParsedAST &&Other);
   ParsedAST &operator=(ParsedAST &&Other);
@@ -141,11 +143,11 @@
   // deferRebuild will hold references to it.
   static std::shared_ptr<CppFile>
   Create(PathRef FileName, tooling::CompileCommand Command,
-         std::shared_ptr<PCHContainerOperations> PCHs);
+         std::shared_ptr<PCHContainerOperations> PCHs, clangd::Logger &Logger);
 
 private:
   CppFile(PathRef FileName, tooling::CompileCommand Command,
-          std::shared_ptr<PCHContainerOperations> PCHs);
+          std::shared_ptr<PCHContainerOperations> PCHs, clangd::Logger &Logger);
 
 public:
   CppFile(CppFile const &) = delete;
@@ -246,18 +248,21 @@
   std::shared_ptr<const PreambleData> LatestAvailablePreamble;
   /// Utility class, required by clang.
   std::shared_ptr<PCHContainerOperations> PCHs;
+  /// Used for logging various messages.
+  clangd::Logger &Logger;
 };
 
 /// Get code completions at a specified \p Pos in \p FileName.
 std::vector<CompletionItem>
 codeComplete(PathRef FileName, tooling::CompileCommand Command,
              PrecompiledPreamble const *Preamble, StringRef Contents,
              Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
              std::shared_ptr<PCHContainerOperations> PCHs,
-             bool SnippetCompletions);
+             bool SnippetCompletions, clangd::Logger &Logger);
 
 /// Get definition of symbol at a specified \p Pos.
-std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos);
+std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos,
+                                      clangd::Logger &Logger);
 
 /// For testing/debugging purposes. Note that this method deserializes all
 /// unserialized Decls, so use with care.
Index: clangd/ClangdUnit.cpp
===================================================================
--- clangd/ClangdUnit.cpp
+++ clangd/ClangdUnit.cpp
@@ -26,6 +26,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/Format.h"
+#include "Logger.h"
 
 #include <algorithm>
 #include <chrono>
@@ -525,7 +526,7 @@
                      PrecompiledPreamble const *Preamble, StringRef Contents,
                      Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
                      std::shared_ptr<PCHContainerOperations> PCHs,
-                     bool SnippetCompletions) {
+                     bool SnippetCompletions, clangd::Logger &Logger) {
   std::vector<const char *> ArgStrs;
   for (const auto &S : Command.CommandLine)
     ArgStrs.push_back(S.c_str());
@@ -583,12 +584,13 @@
 
   SyntaxOnlyAction Action;
   if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
-    // FIXME(ibiryukov): log errors
+    Logger.log("BeginSourceFile() failed when running codeComplete for " +
+               FileName);
     return Items;
   }
-  if (!Action.Execute()) {
-    // FIXME(ibiryukov): log errors
-  }
+  if (!Action.Execute())
+    Logger.log("Execute() failed when running codeComplete for " + FileName);
+
   Action.EndSourceFile();
 
   return Items;
@@ -604,7 +606,8 @@
                  ArrayRef<serialization::DeclID> PreambleDeclIDs,
                  std::unique_ptr<llvm::MemoryBuffer> Buffer,
                  std::shared_ptr<PCHContainerOperations> PCHs,
-                 IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+                 IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                 clangd::Logger &Logger) {
 
   std::vector<DiagWithFixIts> ASTDiags;
   StoreDiagsConsumer UnitDiagsConsumer(/*ref*/ ASTDiags);
@@ -618,13 +621,14 @@
       Clang.get());
 
   auto Action = llvm::make_unique<ClangdFrontendAction>();
-  if (!Action->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
-    // FIXME(ibiryukov): log error
+  const FrontendInputFile &MainInput = Clang->getFrontendOpts().Inputs[0];
+  if (!Action->BeginSourceFile(*Clang, MainInput)) {
+    Logger.log("BeginSourceFile() failed when building AST for " +
+               MainInput.getFile());
     return llvm::None;
   }
-  if (!Action->Execute()) {
-    // FIXME(ibiryukov): log error
-  }
+  if (!Action->Execute())
+    Logger.log("Execute() failed when building AST for " + MainInput.getFile());
 
   // UnitDiagsConsumer is local, we can not store it in CompilerInstance that
   // has a longer lifetime.
@@ -789,7 +793,8 @@
 }
 } // namespace
 
-std::vector<Location> clangd::findDefinitions(ParsedAST &AST, Position Pos) {
+std::vector<Location> clangd::findDefinitions(ParsedAST &AST, Position Pos,
+                                              clangd::Logger &Logger) {
   const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
   const FileEntry *FE = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
   if (!FE)
@@ -889,15 +894,16 @@
 
 std::shared_ptr<CppFile>
 CppFile::Create(PathRef FileName, tooling::CompileCommand Command,
-                std::shared_ptr<PCHContainerOperations> PCHs) {
+                std::shared_ptr<PCHContainerOperations> PCHs, clangd::Logger &Logger) {
   return std::shared_ptr<CppFile>(
-      new CppFile(FileName, std::move(Command), std::move(PCHs)));
+      new CppFile(FileName, std::move(Command), std::move(PCHs), Logger));
 }
 
 CppFile::CppFile(PathRef FileName, tooling::CompileCommand Command,
-                 std::shared_ptr<PCHContainerOperations> PCHs)
+                 std::shared_ptr<PCHContainerOperations> PCHs,
+                 clangd::Logger &Logger)
     : FileName(FileName), Command(std::move(Command)), RebuildCounter(0),
-      RebuildInProgress(false), PCHs(std::move(PCHs)) {
+      RebuildInProgress(false), PCHs(std::move(PCHs)), Logger(Logger) {
 
   std::lock_guard<std::mutex> Lock(Mutex);
   LatestAvailablePreamble = nullptr;
@@ -1078,7 +1084,7 @@
     // Compute updated AST.
     llvm::Optional<ParsedAST> NewAST =
         ParsedAST::Build(std::move(CI), PreambleForAST, SerializedPreambleDecls,
-                         std::move(ContentsBuffer), PCHs, VFS);
+                         std::move(ContentsBuffer), PCHs, VFS, That->Logger);
 
     if (NewAST) {
       Diagnostics.insert(Diagnostics.end(), NewAST->getDiagnostics().begin(),
Index: clangd/ClangdServer.h
===================================================================
--- clangd/ClangdServer.h
+++ clangd/ClangdServer.h
@@ -36,6 +36,8 @@
 
 namespace clangd {
 
+class Logger;
+
 /// Turn a [line, column] pair into an offset in Code.
 size_t positionToOffset(StringRef Code, Position P);
 
@@ -201,10 +203,12 @@
   /// \p DiagConsumer. Note that a callback to \p DiagConsumer happens on a
   /// worker thread. Therefore, instances of \p DiagConsumer must properly
   /// synchronize access to shared state.
+  ///
+  /// Various messages are logged using \p Logger.
   ClangdServer(GlobalCompilationDatabase &CDB,
                DiagnosticsConsumer &DiagConsumer,
                FileSystemProvider &FSProvider, unsigned AsyncThreadsCount,
-               bool SnippetCompletions,
+               bool SnippetCompletions, clangd::Logger &Logger,
                llvm::Optional<StringRef> ResourceDir = llvm::None);
 
   /// Add a \p File to the list of tracked C++ files or update the contents if
@@ -267,6 +271,7 @@
 
   std::future<void> scheduleCancelRebuild(std::shared_ptr<CppFile> Resources);
 
+  clangd::Logger &Logger;
   GlobalCompilationDatabase &CDB;
   DiagnosticsConsumer &DiagConsumer;
   FileSystemProvider &FSProvider;
Index: clangd/ClangdServer.cpp
===================================================================
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -145,8 +145,10 @@
                            DiagnosticsConsumer &DiagConsumer,
                            FileSystemProvider &FSProvider,
                            unsigned AsyncThreadsCount, bool SnippetCompletions,
+                           clangd::Logger &Logger,
                            llvm::Optional<StringRef> ResourceDir)
-    : CDB(CDB), DiagConsumer(DiagConsumer), FSProvider(FSProvider),
+    : Logger(Logger), CDB(CDB), DiagConsumer(DiagConsumer),
+      FSProvider(FSProvider),
       ResourceDir(ResourceDir ? ResourceDir->str() : getStandardResourceDir()),
       PCHs(std::make_shared<PCHContainerOperations>()),
       WorkScheduler(AsyncThreadsCount), SnippetCompletions(SnippetCompletions) {
@@ -157,7 +159,7 @@
 
   auto TaggedFS = FSProvider.getTaggedFileSystem(File);
   std::shared_ptr<CppFile> Resources =
-      Units.getOrCreateFile(File, ResourceDir, CDB, PCHs, TaggedFS.Value);
+      Units.getOrCreateFile(File, ResourceDir, CDB, PCHs, TaggedFS.Value, Logger);
   return scheduleReparseAndDiags(File, VersionedDraft{Version, Contents.str()},
                                  std::move(Resources), std::move(TaggedFS));
 }
@@ -175,7 +177,7 @@
 
   auto TaggedFS = FSProvider.getTaggedFileSystem(File);
   auto Recreated = Units.recreateFileIfCompileCommandChanged(
-      File, ResourceDir, CDB, PCHs, TaggedFS.Value);
+      File, ResourceDir, CDB, PCHs, TaggedFS.Value, Logger);
 
   // Note that std::future from this cleanup action is ignored.
   scheduleCancelRebuild(std::move(Recreated.RemovedFile));
@@ -210,7 +212,7 @@
   std::vector<CompletionItem> Result = clangd::codeComplete(
       File, Resources->getCompileCommand(),
       Preamble ? &Preamble->Preamble : nullptr, *OverridenContents, Pos,
-      TaggedFS.Value, PCHs, SnippetCompletions);
+      TaggedFS.Value, PCHs, SnippetCompletions, Logger);
   return make_tagged(std::move(Result), TaggedFS.Tag);
 }
 
@@ -278,10 +280,10 @@
   assert(Resources && "Calling findDefinitions on non-added file");
 
   std::vector<Location> Result;
-  Resources->getAST().get()->runUnderLock([Pos, &Result](ParsedAST *AST) {
+  Resources->getAST().get()->runUnderLock([Pos, &Result, this](ParsedAST *AST) {
     if (!AST)
       return;
-    Result = clangd::findDefinitions(*AST, Pos);
+    Result = clangd::findDefinitions(*AST, Pos, Logger);
   });
   return make_tagged(std::move(Result), TaggedFS.Tag);
 }
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -223,9 +223,9 @@
 ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,
                                  bool SnippetCompletions,
                                  llvm::Optional<StringRef> ResourceDir)
-    : Out(Out), DiagConsumer(*this),
+    : Out(Out), CDB(/*Logger=*/Out), DiagConsumer(*this),
       Server(CDB, DiagConsumer, FSProvider, AsyncThreadsCount,
-             SnippetCompletions, ResourceDir) {}
+             SnippetCompletions, /*Logger=*/Out, ResourceDir) {}
 
 void ClangdLSPServer::run(std::istream &In) {
   assert(!IsDone && "Run was called before");
Index: clangd/CMakeLists.txt
===================================================================
--- clangd/CMakeLists.txt
+++ clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
   DraftStore.cpp
   GlobalCompilationDatabase.cpp
   JSONRPCDispatcher.cpp
+  Logger.cpp
   Protocol.cpp
   ProtocolHandlers.cpp
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to