Index: clangd/ClangdLSPServer.h =================================================================== --- clangd/ClangdLSPServer.h +++ clangd/ClangdLSPServer.h @@ -73,9 +73,9 @@ void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) override; void onCommand(Ctx C, ExecuteCommandParams &Params) override; void onRename(Ctx C, RenameParams &Parames) override; - std::vector getFixIts(StringRef File, const clangd::Diagnostic &D); - + void onChangeConfiguration(Ctx C, + DidChangeConfigurationParams &Params) override; JSONOutput &Out; /// Used to indicate that the 'shutdown' request was received from the /// Language Server client. Index: clangd/ClangdLSPServer.cpp =================================================================== --- clangd/ClangdLSPServer.cpp +++ clangd/ClangdLSPServer.cpp @@ -9,6 +9,11 @@ #include "ClangdLSPServer.h" #include "JSONRPCDispatcher.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/FormatVariadic.h" @@ -69,6 +74,7 @@ }}, {"definitionProvider", true}, {"documentHighlightProvider", true}, + {"configurationChangeProvider", true}, {"renameProvider", true}, {"executeCommandProvider", json::obj{ @@ -278,6 +284,21 @@ reply(C, json::ary(Highlights->Value)); } +// FIXME: This function needs to be properly tested. +void ClangdLSPServer::onChangeConfiguration( + Ctx C, DidChangeConfigurationParams &Params) { + + // Parse whatever settings might be found inside Params. + ClangdConfigurationParamsChange Settings = Params.settings; + + // Verify if path has value and is a valid path + if (Settings.compilationDatabasePath.hasValue()) { + CDB.setCompileCommandsDir( + Settings.compilationDatabasePath.getValue()); + Server.reparseOpenedFiles(std::move(C)); + } +} + ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount, bool StorePreamblesInMemory, const clangd::CodeCompleteOptions &CCOpts, Index: clangd/ClangdServer.h =================================================================== --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -231,6 +231,11 @@ /// and AST and rebuild them from scratch. std::future forceReparse(Context Ctx, PathRef File); + /// Calls forceReparse() on all currently opened files. + /// As a result, this method may be very expensive. + /// This method is normally called when the compilation database is changed. + std::vector> reparseOpenedFiles(Context Ctx); + /// DEPRECATED. Please use a callback-based version, this API is deprecated /// and will soon be removed. /// @@ -300,12 +305,26 @@ llvm::Expected formatOnType(StringRef Code, PathRef File, Position Pos); - /// Rename all occurrences of the symbol at the \p Pos in \p File to - /// \p NewName. Expected> rename(const Context &Ctx, PathRef File, Position Pos, llvm::StringRef NewName); + /// Modify configuration settings based on what is contained inside + /// ChangedSettings + void changeConfiguration(std::map ChangedSettings); + + + /// Run formatting for \p Rng inside \p File. + std::vector formatRange(PathRef File, Range Rng); + /// Run formatting for the whole \p File. + std::vector formatFile(PathRef File); + /// Run formatting after a character was typed at \p Pos in \p File. + std::vector formatOnType(PathRef File, Position Pos); + /// Rename all occurrences of the symbol at the \p Pos in \p File to + /// \p NewName. + Expected> rename(PathRef File, Position Pos, + llvm::StringRef NewName); + /// Gets current document contents for \p File. \p File must point to a /// currently tracked file. /// FIXME(ibiryukov): This function is here to allow offset-to-Position Index: clangd/ClangdServer.cpp =================================================================== --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -540,6 +540,12 @@ return make_tagged(Result, TaggedFS.Tag); } +void ClangdServer::changeConfiguration( + std::map ChangedSettings) { + if (!ChangedSettings.empty()) { + } +} + std::future ClangdServer::scheduleReparseAndDiags( Context Ctx, PathRef File, VersionedDraft Contents, std::shared_ptr Resources, @@ -616,6 +622,16 @@ return DoneFuture; } +std::vector> ClangdServer::reparseOpenedFiles(Context Ctx) { + std::vector> FutureVector; + std::vector ActiveFilePaths; + ActiveFilePaths = DraftMgr.getActiveFiles(); + for (const auto& FilePath : ActiveFilePaths) + FutureVector.push_back(forceReparse(std::move(Ctx), FilePath)); + + return FutureVector; +} + void ClangdServer::onFileEvent(const DidChangeWatchedFilesParams &Params) { // FIXME: Do nothing for now. This will be used for indexing and potentially // invalidating other caches. Index: clangd/DraftStore.h =================================================================== --- clangd/DraftStore.h +++ clangd/DraftStore.h @@ -40,6 +40,9 @@ /// \return version and contents of the stored document. /// For untracked files, a (0, None) pair is returned. VersionedDraft getDraft(PathRef File) const; + + std::vector getActiveFiles() const; + /// \return version of the tracked document. /// For untracked files, 0 is returned. DocVersion getVersion(PathRef File) const; Index: clangd/DraftStore.cpp =================================================================== --- clangd/DraftStore.cpp +++ clangd/DraftStore.cpp @@ -21,6 +21,16 @@ return It->second; } +std::vector DraftStore::getActiveFiles() const { + std::lock_guard Lock(Mutex); + std::vector ResultVector; + + for (auto Draft : Drafts.keys()) + ResultVector.push_back(Draft); + + return ResultVector; +} + DocVersion DraftStore::getVersion(PathRef File) const { std::lock_guard Lock(Mutex); Index: clangd/GlobalCompilationDatabase.h =================================================================== --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -61,10 +61,17 @@ /// Uses the default fallback command, adding any extra flags. tooling::CompileCommand getFallbackCommand(PathRef File) const override; + void setCompileCommandsDir(Path P) { + std::lock_guard Lock(Mutex); + CompileCommandsDir = P; + CompilationDatabases.clear(); + } + /// Sets the extra flags that should be added to a file. void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); private: + tooling::CompilationDatabase *getCompilationDatabase(PathRef File) const; tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File) const; void addExtraFlags(PathRef File, tooling::CompileCommand &C) const; Index: clangd/GlobalCompilationDatabase.cpp =================================================================== --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -10,6 +10,7 @@ #include "GlobalCompilationDatabase.h" #include "Logger.h" #include "clang/Tooling/CompilationDatabase.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" Index: clangd/Protocol.h =================================================================== --- clangd/Protocol.h +++ clangd/Protocol.h @@ -257,6 +257,24 @@ }; bool fromJSON(const json::Expr &, DidChangeWatchedFilesParams &); +/// Clangd extension to manage a workspace/didChangeConfiguration notification +/// since the data received is described as 'any' type in LSP. +struct ClangdConfigurationParamsChange { + llvm::Optional compilationDatabasePath; +}; +bool fromJSON(const json::Expr &, ClangdConfigurationParamsChange &); + +struct DidChangeConfigurationParams { + DidChangeConfigurationParams() = default; + DidChangeConfigurationParams(ClangdConfigurationParamsChange settings): settings(settings) {} + + // We use this predefined struct because it is easier to use + // than the protocol specified type of 'any'. + ClangdConfigurationParamsChange settings; +}; +bool fromJSON(const json::Expr &, DidChangeConfigurationParams &); +json::Expr toJSON(const DidChangeConfigurationParams &); + struct FormattingOptions { /// Size of a tab in spaces. int tabSize; Index: clangd/Protocol.cpp =================================================================== --- clangd/Protocol.cpp +++ clangd/Protocol.cpp @@ -366,5 +366,21 @@ }; } +bool fromJSON(const json::Expr &Params, DidChangeConfigurationParams &CCP) { + json::ObjectMapper O(Params); + return O && O.map("settings", CCP.settings); +} + +json::Expr toJSON(const DidChangeConfigurationParams &CCP) { + return json::obj{ + {"settings", CCP.settings}, + }; +} + +bool fromJSON(const json::Expr &Params, ClangdConfigurationParamsChange &CCPC) { + json::ObjectMapper O(Params); + return O && O.map("compilationDatabasePath", CCPC.compilationDatabasePath); +} + } // namespace clangd } // namespace clang Index: clangd/ProtocolHandlers.h =================================================================== --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -57,6 +57,8 @@ virtual void onRename(Ctx C, RenameParams &Parames) = 0; virtual void onDocumentHighlight(Ctx C, TextDocumentPositionParams &Params) = 0; + virtual void onChangeConfiguration(Ctx C, + DidChangeConfigurationParams &Params) = 0; }; void registerCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp =================================================================== --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -73,4 +73,6 @@ Register("workspace/executeCommand", &ProtocolCallbacks::onCommand); Register("textDocument/documentHighlight", &ProtocolCallbacks::onDocumentHighlight); + Register("workspace/didChangeConfiguration", + &ProtocolCallbacks::onChangeConfiguration); } Index: test/clangd/initialize-params-invalid.test =================================================================== --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -18,9 +18,10 @@ # CHECK-NEXT: ":" # CHECK-NEXT: ] # CHECK-NEXT: }, +# CHECK-NEXT: "configurationChangeProvider": true, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, -# CHECK-NEXT: "documentHighlightProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT: "firstTriggerCharacter": "}", # CHECK-NEXT: "moreTriggerCharacter": [] Index: test/clangd/initialize-params.test =================================================================== --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -18,9 +18,10 @@ # CHECK-NEXT: ":" # CHECK-NEXT: ] # CHECK-NEXT: }, +# CHECK-NEXT: "configurationChangeProvider": true, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, -# CHECK-NEXT: "documentHighlightProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT: "firstTriggerCharacter": "}", # CHECK-NEXT: "moreTriggerCharacter": [] @@ -49,4 +50,4 @@ # CHECK-NEXT: "result": null Content-Length: 33 -{"jsonrpc":"2.0":"method":"exit"} +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file