rwols updated this revision to Diff 121524.
rwols added a comment.

Use llvm::Error for beautiful handling of errors.

It's perhaps an idea to write a `replyExpected(llvm::Expected<T>)`, that will
transparently handle `llvm::Error`s.

I'll write a unit test for these changes next.

It's probably best to wait for https://reviews.llvm.org/D39435 to land, and 
then rebase.


https://reviews.llvm.org/D39430

Files:
  clangd/ClangdLSPServer.cpp
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  test/clangd/formatting.test

Index: test/clangd/formatting.test
===================================================================
--- test/clangd/formatting.test
+++ test/clangd/formatting.test
@@ -1,4 +1,4 @@
-# RUN: clangd < %s | FileCheck %s
+# RUN: clangd -run-synchronously < %s | FileCheck %s
 # It is absolutely vital that this file has CRLF line endings.
 #
 Content-Length: 125
Index: clangd/JSONRPCDispatcher.h
===================================================================
--- clangd/JSONRPCDispatcher.h
+++ clangd/JSONRPCDispatcher.h
@@ -15,6 +15,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/Error.h"
 #include <iosfwd>
 #include <mutex>
 
@@ -58,6 +59,8 @@
   void reply(const Twine &Result);
   /// Sends an error response to the client, and logs it.
   void replyError(int code, const llvm::StringRef &Message);
+  /// Send all error messages contained in Err to the client, and log them.
+  void replyError(llvm::Error Err);
 
 private:
   JSONOutput &Out;
Index: clangd/JSONRPCDispatcher.cpp
===================================================================
--- clangd/JSONRPCDispatcher.cpp
+++ clangd/JSONRPCDispatcher.cpp
@@ -64,6 +64,11 @@
   }
 }
 
+void RequestContext::replyError(llvm::Error Err) {
+  const auto Message = llvm::toString(std::move(Err));
+  replyError(/*UnknownErrorCode*/ -32001, Message);
+}
+
 void JSONRPCDispatcher::registerHandler(StringRef Method, Handler H) {
   assert(!Handlers.count(Method) && "Handler already registered!");
   Handlers[Method] = std::move(H);
Index: clangd/ClangdServer.h
===================================================================
--- clangd/ClangdServer.h
+++ clangd/ClangdServer.h
@@ -285,11 +285,15 @@
   llvm::Optional<Path> switchSourceHeader(PathRef Path);
 
   /// Run formatting for \p Rng inside \p File.
-  std::vector<tooling::Replacement> formatRange(PathRef File, Range Rng);
+  llvm::Expected<std::vector<tooling::Replacement>> formatRange(PathRef File,
+                                                                Range Rng);
+
   /// Run formatting for the whole \p File.
-  std::vector<tooling::Replacement> formatFile(PathRef File);
+  llvm::Expected<std::vector<tooling::Replacement>> formatFile(PathRef File);
+
   /// Run formatting after a character was typed at \p Pos in \p File.
-  std::vector<tooling::Replacement> formatOnType(PathRef File, Position Pos);
+  llvm::Expected<std::vector<tooling::Replacement>> formatOnType(PathRef File,
+                                                                 Position Pos);
 
   /// Gets current document contents for \p File. \p File must point to a
   /// currently tracked file.
Index: clangd/ClangdServer.cpp
===================================================================
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -34,13 +34,14 @@
   std::promise<void> &Promise;
 };
 
-std::vector<tooling::Replacement> formatCode(StringRef Code, StringRef Filename,
-                                             ArrayRef<tooling::Range> Ranges) {
+llvm::Expected<std::vector<tooling::Replacement>>
+formatCode(StringRef Code, StringRef Filename,
+           ArrayRef<tooling::Range> Ranges) {
   // Call clang-format.
-  // FIXME: Don't ignore style.
-  format::FormatStyle Style = format::getLLVMStyle();
-  auto Result = format::reformat(Style, Code, Ranges, Filename);
-
+  auto StyleOrError = format::getStyle("file", Filename, "LLVM", Code);
+  if (!StyleOrError)
+    return StyleOrError.takeError();
+  auto Result = format::reformat(StyleOrError.get(), Code, Ranges, Filename);
   return std::vector<tooling::Replacement>(Result.begin(), Result.end());
 }
 
@@ -301,23 +302,24 @@
   return make_tagged(std::move(Result), TaggedFS.Tag);
 }
 
-std::vector<tooling::Replacement> ClangdServer::formatRange(PathRef File,
-                                                            Range Rng) {
+llvm::Expected<std::vector<tooling::Replacement>>
+ClangdServer::formatRange(PathRef File, Range Rng) {
   std::string Code = getDocument(File);
 
   size_t Begin = positionToOffset(Code, Rng.start);
   size_t Len = positionToOffset(Code, Rng.end) - Begin;
   return formatCode(Code, File, {tooling::Range(Begin, Len)});
 }
 
-std::vector<tooling::Replacement> ClangdServer::formatFile(PathRef File) {
+llvm::Expected<std::vector<tooling::Replacement>>
+ClangdServer::formatFile(PathRef File) {
   // Format everything.
   std::string Code = getDocument(File);
   return formatCode(Code, File, {tooling::Range(0, Code.size())});
 }
 
-std::vector<tooling::Replacement> ClangdServer::formatOnType(PathRef File,
-                                                             Position Pos) {
+llvm::Expected<std::vector<tooling::Replacement>>
+ClangdServer::formatOnType(PathRef File, Position Pos) {
   // Look for the previous opening brace from the character position and
   // format starting from there.
   std::string Code = getDocument(File);
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -9,6 +9,7 @@
 
 #include "ClangdLSPServer.h"
 #include "JSONRPCDispatcher.h"
+#include <llvm/Support/Error.h>
 
 using namespace clang::clangd;
 using namespace clang;
@@ -91,28 +92,32 @@
 
 void ClangdLSPServer::onDocumentOnTypeFormatting(
     Ctx C, DocumentOnTypeFormattingParams &Params) {
-  auto File = Params.textDocument.uri.file;
-  std::string Code = Server.getDocument(File);
-  std::string Edits =
-      replacementsToEdits(Code, Server.formatOnType(File, Params.position));
-  C.reply("[" + Edits + "]");
+  const auto File = Params.textDocument.uri.file;
+  auto Edits = Server.formatOnType(File, Params.position);
+  if (Edits)
+    C.reply("[" + replacementsToEdits(Server.getDocument(File), *Edits) + "]");
+  else
+    C.replyError(Edits.takeError());
 }
 
 void ClangdLSPServer::onDocumentRangeFormatting(
     Ctx C, DocumentRangeFormattingParams &Params) {
-  auto File = Params.textDocument.uri.file;
-  std::string Code = Server.getDocument(File);
-  std::string Edits =
-      replacementsToEdits(Code, Server.formatRange(File, Params.range));
-  C.reply("[" + Edits + "]");
+  const auto File = Params.textDocument.uri.file;
+  auto Edits = Server.formatRange(File, Params.range);
+  if (Edits)
+    C.reply("[" + replacementsToEdits(Server.getDocument(File), *Edits) + "]");
+  else
+    C.replyError(Edits.takeError());
 }
 
 void ClangdLSPServer::onDocumentFormatting(Ctx C,
                                            DocumentFormattingParams &Params) {
-  auto File = Params.textDocument.uri.file;
-  std::string Code = Server.getDocument(File);
-  std::string Edits = replacementsToEdits(Code, Server.formatFile(File));
-  C.reply("[" + Edits + "]");
+  const auto File = Params.textDocument.uri.file;
+  auto Edits = Server.formatFile(File);
+  if (Edits)
+    C.reply("[" + replacementsToEdits(Server.getDocument(File), *Edits) + "]");
+  else
+    C.replyError(Edits.takeError());
 }
 
 void ClangdLSPServer::onCodeAction(Ctx C, CodeActionParams &Params) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to