Nebiroth created this revision.

Implementation of DidChangeConfiguration notification handling in clangd.
This currently only supports changing one setting: the path of the compilation 
database to be used for the current project
In other words, it is no longer necessary to restart clangd with a different 
command line argument in order to change
the compilation database.


https://reviews.llvm.org/D39571

Files:
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/GlobalCompilationDatabase.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h

Index: clangd/ProtocolHandlers.h
===================================================================
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -52,6 +52,8 @@
   virtual void onGoToDefinition(Ctx C, TextDocumentPositionParams &Params) = 0;
   virtual void onSwitchSourceHeader(Ctx C, TextDocumentIdentifier &Params) = 0;
   virtual void onFileEvent(Ctx C, DidChangeWatchedFilesParams &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
@@ -72,4 +72,6 @@
   Register("textDocument/switchSourceHeader",
            &ProtocolCallbacks::onSwitchSourceHeader);
   Register("workspace/didChangeWatchedFiles", &ProtocolCallbacks::onFileEvent);
+  Register("workspace/didChangeConfiguration",
+           &ProtocolCallbacks::onChangeConfiguration);
 }
Index: clangd/Protocol.h
===================================================================
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -273,6 +273,27 @@
   parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
 };
 
+struct ClangdConfigurationParams {
+
+  llvm::Optional<std::string> compilationDatabasePath;
+  static llvm::Optional<ClangdConfigurationParams>
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
+};
+
+struct DidChangeConfigurationParams {
+
+  DidChangeConfigurationParams() {}
+
+  DidChangeConfigurationParams(ClangdConfigurationParams settings)
+      : settings(settings) {}
+
+  ClangdConfigurationParams settings;
+
+  static llvm::Optional<DidChangeConfigurationParams>
+  parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger);
+  static std::string unparse(const DidChangeConfigurationParams &P);
+};
+
 struct FormattingOptions {
   /// Size of a tab in spaces.
   int tabSize;
Index: clangd/Protocol.cpp
===================================================================
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -531,6 +531,59 @@
   return Result;
 }
 
+llvm::Optional<DidChangeConfigurationParams>
+DidChangeConfigurationParams::parse(llvm::yaml::MappingNode *Params,
+                                    clangd::Logger &Logger) {
+  DidChangeConfigurationParams Result;
+  for (auto &NextKeyValue : *Params) {
+    auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+    if (!KeyString)
+      return llvm::None;
+
+    llvm::SmallString<10> KeyStorage;
+    StringRef KeyValue = KeyString->getValue(KeyStorage);
+    auto *Value =
+        dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
+    if (!Value)
+      return llvm::None;
+
+    llvm::SmallString<10> Storage;
+    if (KeyValue == "settings") {
+      auto Parsed = ClangdConfigurationParams::parse(Value, Logger);
+      if (!Parsed)
+        return llvm::None;
+      Result.settings = Parsed.getValue();
+    } else {
+      logIgnoredField(KeyValue, Logger);
+    }
+  }
+
+  return Result;
+}
+
+llvm::Optional<ClangdConfigurationParams>
+ClangdConfigurationParams::parse(llvm::yaml::MappingNode *Params,
+                                 clangd::Logger &Logger) {
+  ClangdConfigurationParams Result;
+  for (auto &NextKeyValue : *Params) {
+    auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+    if (!KeyString)
+      return llvm::None;
+
+    llvm::SmallString<10> KeyStorage;
+    StringRef KeyValue = KeyString->getValue(KeyStorage);
+    auto *Value =
+        dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
+    if (!Value)
+      return llvm::None;
+
+    if (KeyValue == "compilationDatabasePath") {
+      Result.compilationDatabasePath = Value->getValue(KeyStorage);
+    }
+  }
+  return Result;
+}
+
 llvm::Optional<TextDocumentContentChangeEvent>
 TextDocumentContentChangeEvent::parse(llvm::yaml::MappingNode *Params,
                                       clangd::Logger &Logger) {
Index: clangd/GlobalCompilationDatabase.h
===================================================================
--- clangd/GlobalCompilationDatabase.h
+++ clangd/GlobalCompilationDatabase.h
@@ -52,11 +52,14 @@
 
   std::vector<tooling::CompileCommand>
   getCompileCommands(PathRef File) override;
+  llvm::Optional<Path> getCompileCommandsDir() { return CompileCommandsDir; }
+  void setCompileCommandsDir(Path P) { CompileCommandsDir = P; }
+
+  tooling::CompilationDatabase *getCompilationDatabase(PathRef File);
 
   void setExtraFlagsForFile(PathRef File, std::vector<std::string> ExtraFlags);
 
 private:
-  tooling::CompilationDatabase *getCompilationDatabase(PathRef File);
   tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File);
 
   std::mutex Mutex;
Index: clangd/ClangdServer.h
===================================================================
--- clangd/ClangdServer.h
+++ clangd/ClangdServer.h
@@ -284,6 +284,10 @@
   /// given a header file and vice versa.
   llvm::Optional<Path> switchSourceHeader(PathRef Path);
 
+  /// Modify configuration settings based on what is contained inside
+  /// ChangedSettings
+  void changeConfiguration(std::map<std::string, std::string> ChangedSettings);
+
   /// Run formatting for \p Rng inside \p File.
   std::vector<tooling::Replacement> formatRange(PathRef File, Range Rng);
   /// Run formatting for the whole \p File.
Index: clangd/ClangdServer.cpp
===================================================================
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -434,6 +434,14 @@
   return llvm::None;
 }
 
+// Empty function for now. Once more settings can be handled by server instance they will be processed here.
+
+void ClangdServer::changeConfiguration(
+    std::map<std::string, std::string> ChangedSettings) {
+  if (!ChangedSettings.empty()) {
+  }
+}
+
 std::future<void> ClangdServer::scheduleReparseAndDiags(
     PathRef File, VersionedDraft Contents, std::shared_ptr<CppFile> Resources,
     Tagged<IntrusiveRefCntPtr<vfs::FileSystem>> TaggedFS) {
Index: clangd/ClangdLSPServer.h
===================================================================
--- clangd/ClangdLSPServer.h
+++ clangd/ClangdLSPServer.h
@@ -69,6 +69,8 @@
   void onGoToDefinition(Ctx C, TextDocumentPositionParams &Params) override;
   void onSwitchSourceHeader(Ctx C, TextDocumentIdentifier &Params) override;
   void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) override;
+  void onChangeConfiguration(Ctx C,
+                             DidChangeConfigurationParams &Params) override;
 
   std::vector<clang::tooling::Replacement>
   getFixIts(StringRef File, const clangd::Diagnostic &D);
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -47,7 +47,8 @@
           "codeActionProvider": true,
           "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]},
           "signatureHelpProvider": {"triggerCharacters": ["(",","]},
-          "definitionProvider": true
+          "definitionProvider": true,
+          "configurationChangeProvider": true
         }})");
   if (Params.rootUri && !Params.rootUri->file.empty())
     Server.setRootPath(Params.rootUri->file);
@@ -193,6 +194,20 @@
   C.reply(Result ? URI::unparse(URI::fromFile(*Result)) : R"("")");
 }
 
+void ClangdLSPServer::onChangeConfiguration(
+    Ctx C, DidChangeConfigurationParams &Params) {
+  std::map<std::string, std::string> SettingsMap;
+  SettingsMap.insert(std::pair<std::string, std::string>(
+      "CDBPath", Params.settings.compilationDatabasePath.getValue()));
+  CDB.setCompileCommandsDir(Params.settings.compilationDatabasePath.getValue());
+  CDB.getCompilationDatabase(StringRef(CDB.getCompileCommandsDir().getValue()));
+
+  // There is nothing in this function yet but any change in settings that needs
+  // to be trickled down to the ClangdServer instance needs to be added to the
+  // map and sent with this function call.
+  Server.changeConfiguration(SettingsMap);
+}
+
 ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,
                                  bool SnippetCompletions,
                                  llvm::Optional<StringRef> ResourceDir,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to