[clang-tools-extra] r314309 - [clangd] Handle InitializeParams and store rootUri

Marc-Andre Laperle via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 27 08:31:18 PDT 2017


Author: malaperle
Date: Wed Sep 27 08:31:17 2017
New Revision: 314309

URL: http://llvm.org/viewvc/llvm-project?rev=314309&view=rev
Log:
[clangd] Handle InitializeParams and store rootUri

Summary:
The root Uri is the workspace location and will be useful in the context of
indexing. We could also add more things to InitializeParams in order to
configure Clangd for C/C++ sepecific extensions.

Reviewers: ilya-biryukov, bkramer, krasimir, Nebiroth

Reviewed By: ilya-biryukov

Subscribers: ilya-biryukov

Tags: #clang-tools-extra

Differential Revision: https://reviews.llvm.org/D38093

Added:
    clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test
    clang-tools-extra/trunk/test/clangd/initialize-params.test
Modified:
    clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
    clang-tools-extra/trunk/clangd/ClangdServer.cpp
    clang-tools-extra/trunk/clangd/ClangdServer.h
    clang-tools-extra/trunk/clangd/Protocol.cpp
    clang-tools-extra/trunk/clangd/Protocol.h
    clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
    clang-tools-extra/trunk/clangd/ProtocolHandlers.h

Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=314309&r1=314308&r2=314309&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Wed Sep 27 08:31:17 2017
@@ -51,7 +51,8 @@ class ClangdLSPServer::LSPProtocolCallba
 public:
   LSPProtocolCallbacks(ClangdLSPServer &LangServer) : LangServer(LangServer) {}
 
-  void onInitialize(StringRef ID, JSONOutput &Out) override;
+  void onInitialize(StringRef ID, InitializeParams IP,
+                    JSONOutput &Out) override;
   void onShutdown(JSONOutput &Out) override;
   void onDocumentDidOpen(DidOpenTextDocumentParams Params,
                          JSONOutput &Out) override;
@@ -77,6 +78,7 @@ private:
 };
 
 void ClangdLSPServer::LSPProtocolCallbacks::onInitialize(StringRef ID,
+                                                         InitializeParams IP,
                                                          JSONOutput &Out) {
   Out.writeMessage(
       R"({"jsonrpc":"2.0","id":)" + ID +
@@ -89,6 +91,10 @@ void ClangdLSPServer::LSPProtocolCallbac
           "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]},
           "definitionProvider": true
         }}})");
+  if (IP.rootUri && !IP.rootUri->file.empty())
+    LangServer.Server.setRootPath(IP.rootUri->file);
+  else if (IP.rootPath && !IP.rootPath->empty())
+    LangServer.Server.setRootPath(*IP.rootPath);
 }
 
 void ClangdLSPServer::LSPProtocolCallbacks::onShutdown(JSONOutput &Out) {

Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=314309&r1=314308&r2=314309&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Wed Sep 27 08:31:17 2017
@@ -15,6 +15,7 @@
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
 #include <future>
 
@@ -154,12 +155,19 @@ ClangdServer::ClangdServer(GlobalCompila
       SnippetCompletions(SnippetCompletions), WorkScheduler(AsyncThreadsCount) {
 }
 
+void ClangdServer::setRootPath(PathRef RootPath) {
+  std::string NewRootPath = llvm::sys::path::convert_to_slash(
+      RootPath, llvm::sys::path::Style::posix);
+  if (llvm::sys::fs::is_directory(NewRootPath))
+    this->RootPath = NewRootPath;
+}
+
 std::future<void> ClangdServer::addDocument(PathRef File, StringRef Contents) {
   DocVersion Version = DraftMgr.updateDraft(File, Contents);
 
   auto TaggedFS = FSProvider.getTaggedFileSystem(File);
-  std::shared_ptr<CppFile> Resources =
-      Units.getOrCreateFile(File, ResourceDir, CDB, PCHs, TaggedFS.Value, Logger);
+  std::shared_ptr<CppFile> Resources = Units.getOrCreateFile(
+      File, ResourceDir, CDB, PCHs, TaggedFS.Value, Logger);
   return scheduleReparseAndDiags(File, VersionedDraft{Version, Contents.str()},
                                  std::move(Resources), std::move(TaggedFS));
 }

Modified: clang-tools-extra/trunk/clangd/ClangdServer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=314309&r1=314308&r2=314309&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.h Wed Sep 27 08:31:17 2017
@@ -211,6 +211,9 @@ public:
                bool SnippetCompletions, clangd::Logger &Logger,
                llvm::Optional<StringRef> ResourceDir = llvm::None);
 
+  /// Set the root path of the workspace.
+  void setRootPath(PathRef RootPath);
+
   /// Add a \p File to the list of tracked C++ files or update the contents if
   /// \p File is already tracked. Also schedules parsing of the AST for it on a
   /// separate thread. When the parsing is complete, DiagConsumer passed in
@@ -278,6 +281,8 @@ private:
   DraftStore DraftMgr;
   CppFileCollection Units;
   std::string ResourceDir;
+  // If set, this represents the workspace path.
+  llvm::Optional<std::string> RootPath;
   std::shared_ptr<PCHContainerOperations> PCHs;
   bool SnippetCompletions;
   /// Used to serialize diagnostic callbacks.

Modified: clang-tools-extra/trunk/clangd/Protocol.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.cpp?rev=314309&r1=314308&r2=314309&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.cpp (original)
+++ clang-tools-extra/trunk/clangd/Protocol.cpp Wed Sep 27 08:31:17 2017
@@ -286,6 +286,63 @@ std::string TextEdit::unparse(const Text
   return Result;
 }
 
+namespace {
+TraceLevel getTraceLevel(llvm::StringRef TraceLevelStr,
+                         clangd::Logger &Logger) {
+  if (TraceLevelStr == "off")
+    return TraceLevel::Off;
+  else if (TraceLevelStr == "messages")
+    return TraceLevel::Messages;
+  else if (TraceLevelStr == "verbose")
+    return TraceLevel::Verbose;
+
+  Logger.log(llvm::formatv("Unknown trace level \"{0}\"\n", TraceLevelStr));
+  return TraceLevel::Off;
+}
+} // namespace
+
+llvm::Optional<InitializeParams>
+InitializeParams::parse(llvm::yaml::MappingNode *Params,
+                        clangd::Logger &Logger) {
+  InitializeParams 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)
+      continue;
+
+    if (KeyValue == "processId") {
+      auto *Value =
+          dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
+      if (!Value)
+        return llvm::None;
+      long long Val;
+      if (llvm::getAsSignedInteger(Value->getValue(KeyStorage), 0, Val))
+        return llvm::None;
+      Result.processId = Val;
+    } else if (KeyValue == "rootPath") {
+      Result.rootPath = Value->getValue(KeyStorage);
+    } else if (KeyValue == "rootUri") {
+      Result.rootUri = URI::parse(Value);
+    } else if (KeyValue == "initializationOptions") {
+      // Not used
+    } else if (KeyValue == "capabilities") {
+      // Not used
+    } else if (KeyValue == "trace") {
+      Result.trace = getTraceLevel(Value->getValue(KeyStorage), Logger);
+    } else {
+      logIgnoredField(KeyValue, Logger);
+    }
+  }
+  return Result;
+}
+
 llvm::Optional<DidOpenTextDocumentParams>
 DidOpenTextDocumentParams::parse(llvm::yaml::MappingNode *Params,
                                  clangd::Logger &Logger) {

Modified: clang-tools-extra/trunk/clangd/Protocol.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.h?rev=314309&r1=314308&r2=314309&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.h (original)
+++ clang-tools-extra/trunk/clangd/Protocol.h Wed Sep 27 08:31:17 2017
@@ -160,6 +160,43 @@ struct TextDocumentItem {
                                                 clangd::Logger &Logger);
 };
 
+enum class TraceLevel {
+  Off = 0,
+  Messages = 1,
+  Verbose = 2,
+};
+
+struct InitializeParams {
+  /// The process Id of the parent process that started
+  /// the server. Is null if the process has not been started by another
+  /// process. If the parent process is not alive then the server should exit
+  /// (see exit notification) its process.
+  llvm::Optional<int> processId;
+
+  /// The rootPath of the workspace. Is null
+  /// if no folder is open.
+  ///
+  /// @deprecated in favour of rootUri.
+  llvm::Optional<std::string> rootPath;
+
+  /// The rootUri of the workspace. Is null if no
+  /// folder is open. If both `rootPath` and `rootUri` are set
+  /// `rootUri` wins.
+  llvm::Optional<URI> rootUri;
+
+  // User provided initialization options.
+  // initializationOptions?: any;
+
+  /// The capabilities provided by the client (editor or tool)
+  /// Note: Not currently used by clangd
+  // ClientCapabilities capabilities;
+
+  /// The initial trace setting. If omitted trace is disabled ('off').
+  llvm::Optional<TraceLevel> trace;
+  static llvm::Optional<InitializeParams> parse(llvm::yaml::MappingNode *Params,
+                                                clangd::Logger &Logger);
+};
+
 struct DidOpenTextDocumentParams {
   /// The document that was opened.
   TextDocumentItem textDocument;

Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp?rev=314309&r1=314308&r2=314309&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp (original)
+++ clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp Wed Sep 27 08:31:17 2017
@@ -21,7 +21,13 @@ struct InitializeHandler : Handler {
       : Handler(Output), Callbacks(Callbacks) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    Callbacks.onInitialize(ID, Output);
+    auto IP = InitializeParams::parse(Params, Output);
+    if (!IP) {
+      Output.log("Failed to decode InitializeParams!\n");
+      IP = InitializeParams();
+    }
+
+    Callbacks.onInitialize(ID, *IP, Output);
   }
 
 private:

Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.h?rev=314309&r1=314308&r2=314309&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ProtocolHandlers.h (original)
+++ clang-tools-extra/trunk/clangd/ProtocolHandlers.h Wed Sep 27 08:31:17 2017
@@ -27,7 +27,8 @@ class ProtocolCallbacks {
 public:
   virtual ~ProtocolCallbacks() = default;
 
-  virtual void onInitialize(StringRef ID, JSONOutput &Out) = 0;
+  virtual void onInitialize(StringRef ID, InitializeParams IP,
+                            JSONOutput &Out) = 0;
   virtual void onShutdown(JSONOutput &Out) = 0;
   virtual void onDocumentDidOpen(DidOpenTextDocumentParams Params,
                                  JSONOutput &Out) = 0;

Added: clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test?rev=314309&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test (added)
+++ clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test Wed Sep 27 08:31:17 2017
@@ -0,0 +1,21 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s
+# It is absolutely vital that this file has CRLF line endings.
+#
+# Test with invalid initialize request parameters
+Content-Length: 142
+
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":"","rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}}
+# CHECK: Content-Length: 466
+# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{
+# CHECK:   "textDocumentSync": 1,
+# CHECK:   "documentFormattingProvider": true,
+# CHECK:   "documentRangeFormattingProvider": true,
+# CHECK:   "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},
+# CHECK:   "codeActionProvider": true,
+# CHECK:   "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]},
+# CHECK:   "definitionProvider": true
+# CHECK: }}}
+#
+Content-Length: 44
+
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}

Added: clang-tools-extra/trunk/test/clangd/initialize-params.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/initialize-params.test?rev=314309&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clangd/initialize-params.test (added)
+++ clang-tools-extra/trunk/test/clangd/initialize-params.test Wed Sep 27 08:31:17 2017
@@ -0,0 +1,21 @@
+# RUN: clangd -run-synchronously < %s | FileCheck %s
+# It is absolutely vital that this file has CRLF line endings.
+#
+# Test initialize request parameters with rootUri
+Content-Length: 143
+
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}}
+# CHECK: Content-Length: 466
+# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{
+# CHECK:   "textDocumentSync": 1,
+# CHECK:   "documentFormattingProvider": true,
+# CHECK:   "documentRangeFormattingProvider": true,
+# CHECK:   "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]},
+# CHECK:   "codeActionProvider": true,
+# CHECK:   "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]},
+# CHECK:   "definitionProvider": true
+# CHECK: }}}
+#
+Content-Length: 44
+
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}




More information about the cfe-commits mailing list