Index: clang-tools-extra/trunk/clangd/CMakeLists.txt =================================================================== --- clang-tools-extra/trunk/clangd/CMakeLists.txt +++ clang-tools-extra/trunk/clangd/CMakeLists.txt @@ -10,6 +10,7 @@ DraftStore.cpp GlobalCompilationDatabase.cpp JSONRPCDispatcher.cpp + Logger.cpp Protocol.cpp ProtocolHandlers.cpp Index: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp =================================================================== --- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp +++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp @@ -223,9 +223,9 @@ ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount, bool SnippetCompletions, llvm::Optional 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: clang-tools-extra/trunk/clangd/ClangdServer.h =================================================================== --- clang-tools-extra/trunk/clangd/ClangdServer.h +++ clang-tools-extra/trunk/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 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 scheduleCancelRebuild(std::shared_ptr Resources); + clangd::Logger &Logger; GlobalCompilationDatabase &CDB; DiagnosticsConsumer &DiagConsumer; FileSystemProvider &FSProvider; Index: clang-tools-extra/trunk/clangd/ClangdServer.cpp =================================================================== --- clang-tools-extra/trunk/clangd/ClangdServer.cpp +++ clang-tools-extra/trunk/clangd/ClangdServer.cpp @@ -145,8 +145,10 @@ DiagnosticsConsumer &DiagConsumer, FileSystemProvider &FSProvider, unsigned AsyncThreadsCount, bool SnippetCompletions, + clangd::Logger &Logger, llvm::Optional ResourceDir) - : CDB(CDB), DiagConsumer(DiagConsumer), FSProvider(FSProvider), + : Logger(Logger), CDB(CDB), DiagConsumer(DiagConsumer), + FSProvider(FSProvider), ResourceDir(ResourceDir ? ResourceDir->str() : getStandardResourceDir()), PCHs(std::make_shared()), WorkScheduler(AsyncThreadsCount), SnippetCompletions(SnippetCompletions) { @@ -157,7 +159,7 @@ auto TaggedFS = FSProvider.getTaggedFileSystem(File); std::shared_ptr 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 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 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: clang-tools-extra/trunk/clangd/ClangdUnit.h =================================================================== --- clang-tools-extra/trunk/clangd/ClangdUnit.h +++ clang-tools-extra/trunk/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 PreambleDeclIDs, std::unique_ptr Buffer, std::shared_ptr PCHs, - IntrusiveRefCntPtr VFS); + IntrusiveRefCntPtr 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 Create(PathRef FileName, tooling::CompileCommand Command, - std::shared_ptr PCHs); + std::shared_ptr PCHs, clangd::Logger &Logger); private: CppFile(PathRef FileName, tooling::CompileCommand Command, - std::shared_ptr PCHs); + std::shared_ptr PCHs, clangd::Logger &Logger); public: CppFile(CppFile const &) = delete; @@ -246,6 +248,8 @@ std::shared_ptr LatestAvailablePreamble; /// Utility class, required by clang. std::shared_ptr PCHs; + /// Used for logging various messages. + clangd::Logger &Logger; }; /// Get code completions at a specified \p Pos in \p FileName. @@ -254,10 +258,11 @@ PrecompiledPreamble const *Preamble, StringRef Contents, Position Pos, IntrusiveRefCntPtr VFS, std::shared_ptr PCHs, - bool SnippetCompletions); + bool SnippetCompletions, clangd::Logger &Logger); /// Get definition of symbol at a specified \p Pos. -std::vector findDefinitions(ParsedAST &AST, Position Pos); +std::vector 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: clang-tools-extra/trunk/clangd/ClangdUnit.cpp =================================================================== --- clang-tools-extra/trunk/clangd/ClangdUnit.cpp +++ clang-tools-extra/trunk/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 #include @@ -525,7 +526,7 @@ PrecompiledPreamble const *Preamble, StringRef Contents, Position Pos, IntrusiveRefCntPtr VFS, std::shared_ptr PCHs, - bool SnippetCompletions) { + bool SnippetCompletions, clangd::Logger &Logger) { std::vector 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 PreambleDeclIDs, std::unique_ptr Buffer, std::shared_ptr PCHs, - IntrusiveRefCntPtr VFS) { + IntrusiveRefCntPtr VFS, + clangd::Logger &Logger) { std::vector ASTDiags; StoreDiagsConsumer UnitDiagsConsumer(/*ref*/ ASTDiags); @@ -618,13 +621,14 @@ Clang.get()); auto Action = llvm::make_unique(); - 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 clangd::findDefinitions(ParsedAST &AST, Position Pos) { +std::vector 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::Create(PathRef FileName, tooling::CompileCommand Command, - std::shared_ptr PCHs) { + std::shared_ptr PCHs, clangd::Logger &Logger) { return std::shared_ptr( - 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 PCHs) + std::shared_ptr 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 Lock(Mutex); LatestAvailablePreamble = nullptr; @@ -1078,7 +1084,7 @@ // Compute updated AST. llvm::Optional 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: clang-tools-extra/trunk/clangd/ClangdUnitStore.h =================================================================== --- clang-tools-extra/trunk/clangd/ClangdUnitStore.h +++ clang-tools-extra/trunk/clangd/ClangdUnitStore.h @@ -20,14 +20,15 @@ namespace clang { namespace clangd { +class Logger; + /// Thread-safe mapping from FileNames to CppFile. class CppFileCollection { public: - std::shared_ptr - getOrCreateFile(PathRef File, PathRef ResourceDir, - GlobalCompilationDatabase &CDB, - std::shared_ptr PCHs, - IntrusiveRefCntPtr VFS) { + std::shared_ptr getOrCreateFile( + PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB, + std::shared_ptr PCHs, + IntrusiveRefCntPtr VFS, clangd::Logger &Logger) { std::lock_guard Lock(Mutex); auto It = OpenedFiles.find(File); @@ -36,7 +37,7 @@ 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 PCHs, - IntrusiveRefCntPtr VFS); + IntrusiveRefCntPtr VFS, clangd::Logger &Logger); std::shared_ptr getFile(PathRef File) { std::lock_guard Lock(Mutex); Index: clang-tools-extra/trunk/clangd/ClangdUnitStore.cpp =================================================================== --- clang-tools-extra/trunk/clangd/ClangdUnitStore.cpp +++ clang-tools-extra/trunk/clangd/ClangdUnitStore.cpp @@ -30,7 +30,7 @@ CppFileCollection::recreateFileIfCompileCommandChanged( PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB, std::shared_ptr PCHs, - IntrusiveRefCntPtr VFS) { + IntrusiveRefCntPtr VFS, clangd::Logger &Logger) { auto NewCommand = getCompileCommand(CDB, File, ResourceDir); std::lock_guard 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: clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h =================================================================== --- clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.h +++ clang-tools-extra/trunk/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 getCompileCommands(PathRef File) override; @@ -61,6 +65,8 @@ /// Stores extra flags per file. llvm::StringMap> ExtraFlagsForFile; + /// Used for logging. + clangd::Logger &Logger; }; } // namespace clangd } // namespace clang Index: clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp =================================================================== --- clang-tools-extra/trunk/clangd/GlobalCompilationDatabase.cpp +++ clang-tools-extra/trunk/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 DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) { std::vector 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: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h =================================================================== --- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h +++ clang-tools-extra/trunk/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,7 +22,7 @@ /// 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) {} @@ -30,7 +31,7 @@ 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: clang-tools-extra/trunk/clangd/Logger.h =================================================================== --- clang-tools-extra/trunk/clangd/Logger.h +++ clang-tools-extra/trunk/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: clang-tools-extra/trunk/clangd/Logger.cpp =================================================================== --- clang-tools-extra/trunk/clangd/Logger.cpp +++ clang-tools-extra/trunk/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: clang-tools-extra/trunk/clangd/Protocol.h =================================================================== --- clang-tools-extra/trunk/clangd/Protocol.h +++ clang-tools-extra/trunk/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 - parse(llvm::yaml::MappingNode *Params, JSONOutput &Output); + parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); }; struct Position { @@ -79,7 +79,7 @@ } static llvm::Optional parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output); + clangd::Logger &Logger); static std::string unparse(const Position &P); }; @@ -98,7 +98,7 @@ } static llvm::Optional parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output); + clangd::Logger &Logger); static std::string unparse(const Range &P); }; @@ -126,7 +126,7 @@ std::vector extraFlags; static llvm::Optional parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output); + clangd::Logger &Logger); }; struct TextEdit { @@ -139,7 +139,7 @@ std::string newText; static llvm::Optional 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 parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output); + clangd::Logger &Logger); }; struct DidOpenTextDocumentParams { @@ -168,7 +168,7 @@ llvm::Optional metadata; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, JSONOutput &Output); + parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); }; struct DidCloseTextDocumentParams { @@ -176,7 +176,7 @@ TextDocumentIdentifier textDocument; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, JSONOutput &Output); + parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); }; struct TextDocumentContentChangeEvent { @@ -184,7 +184,7 @@ std::string text; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, JSONOutput &Output); + parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); }; struct DidChangeTextDocumentParams { @@ -197,7 +197,7 @@ std::vector contentChanges; static llvm::Optional - 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 - 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 - 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 - 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 - parse(llvm::yaml::MappingNode *Params, JSONOutput &Output); + parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); }; struct Diagnostic { @@ -284,7 +284,7 @@ } static llvm::Optional parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output); + clangd::Logger &Logger); }; struct CodeActionContext { @@ -292,7 +292,7 @@ std::vector diagnostics; static llvm::Optional - 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 parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output); + clangd::Logger &Logger); }; struct TextDocumentPositionParams { @@ -317,7 +317,7 @@ Position position; static llvm::Optional - parse(llvm::yaml::MappingNode *Params, JSONOutput &Output); + parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); }; /// The kind of a completion entry. Index: clang-tools-extra/trunk/clangd/Protocol.cpp =================================================================== --- clang-tools-extra/trunk/clangd/Protocol.cpp +++ clang-tools-extra/trunk/clangd/Protocol.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "Protocol.h" -#include "JSONRPCDispatcher.h" +#include "Logger.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallString.h" @@ -21,11 +21,13 @@ #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::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { TextDocumentIdentifier Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(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::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { Position Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(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::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { Range Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(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::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(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::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { Metadata Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(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::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { TextEdit Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -260,7 +262,7 @@ auto *Map = dyn_cast(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::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { DidOpenTextDocumentParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -302,17 +304,17 @@ 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; @@ -320,7 +322,7 @@ llvm::Optional DidCloseTextDocumentParams::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { DidCloseTextDocumentParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -335,12 +337,12 @@ auto *Map = dyn_cast(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; @@ -348,7 +350,7 @@ llvm::Optional DidChangeTextDocumentParams::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { DidChangeTextDocumentParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -364,7 +366,7 @@ auto *Map = dyn_cast(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,13 +378,13 @@ auto *I = dyn_cast(&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; @@ -390,7 +392,7 @@ llvm::Optional TextDocumentContentChangeEvent::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { TextDocumentContentChangeEvent Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(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::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(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::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { DocumentRangeFormattingParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -479,22 +481,22 @@ 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; @@ -502,7 +504,7 @@ llvm::Optional DocumentOnTypeFormattingParams::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { DocumentOnTypeFormattingParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -527,22 +529,22 @@ 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; @@ -550,7 +552,7 @@ llvm::Optional DocumentFormattingParams::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { DocumentFormattingParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(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::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { Diagnostic Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(NextKeyValue.getKey()); @@ -599,7 +601,7 @@ dyn_cast_or_null(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::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(NextKeyValue.getKey()); @@ -650,20 +652,20 @@ auto *I = dyn_cast(&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::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(NextKeyValue.getKey()); @@ -679,22 +681,22 @@ 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; @@ -702,7 +704,7 @@ llvm::Optional TextDocumentPositionParams::parse(llvm::yaml::MappingNode *Params, - JSONOutput &Output) { + clangd::Logger &Logger) { TextDocumentPositionParams Result; for (auto &NextKeyValue : *Params) { auto *KeyString = dyn_cast(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: clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp =================================================================== --- clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp +++ clang-tools-extra/trunk/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;