[clang-tools-extra] r320524 - [clangd] (Attempt to) read clang-format file for document formatting

Raoul Wols via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 12 12:25:06 PST 2017


Author: rwols
Date: Tue Dec 12 12:25:06 2017
New Revision: 320524

URL: http://llvm.org/viewvc/llvm-project?rev=320524&view=rev
Log:
[clangd] (Attempt to) read clang-format file for document formatting

Summary:
Takes into account the clang-format file of the project, if any.
Reverts to LLVM if nothing is found. Replies with an error if any error occured.
For instance, a parse error in the clang-format YAML file.

Reviewers: ilya-biryukov, sammccall, Nebiroth, malaperle, krasimir

Reviewed By: sammccall

Subscribers: cfe-commits

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


Modified:
    clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
    clang-tools-extra/trunk/clangd/ClangdServer.cpp
    clang-tools-extra/trunk/clangd/ClangdServer.h

Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=320524&r1=320523&r2=320524&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Tue Dec 12 12:25:06 2017
@@ -17,18 +17,29 @@ using namespace clang;
 
 namespace {
 
+TextEdit replacementToEdit(StringRef Code, const tooling::Replacement &R) {
+  Range ReplacementRange = {
+      offsetToPosition(Code, R.getOffset()),
+      offsetToPosition(Code, R.getOffset() + R.getLength())};
+  return {ReplacementRange, R.getReplacementText()};
+}
+
 std::vector<TextEdit>
 replacementsToEdits(StringRef Code,
                     const std::vector<tooling::Replacement> &Replacements) {
   // Turn the replacements into the format specified by the Language Server
   // Protocol. Fuse them into one big JSON array.
   std::vector<TextEdit> Edits;
-  for (auto &R : Replacements) {
-    Range ReplacementRange = {
-        offsetToPosition(Code, R.getOffset()),
-        offsetToPosition(Code, R.getOffset() + R.getLength())};
-    Edits.push_back({ReplacementRange, R.getReplacementText()});
-  }
+  for (const auto &R : Replacements)
+    Edits.push_back(replacementToEdit(Code, R));
+  return Edits;
+}
+
+std::vector<TextEdit> replacementsToEdits(StringRef Code,
+                                          const tooling::Replacements &Repls) {
+  std::vector<TextEdit> Edits;
+  for (const auto &R : Repls)
+    Edits.push_back(replacementToEdit(Code, R));
   return Edits;
 }
 
@@ -153,23 +164,36 @@ void ClangdLSPServer::onDocumentOnTypeFo
     Ctx C, DocumentOnTypeFormattingParams &Params) {
   auto File = Params.textDocument.uri.file;
   std::string Code = Server.getDocument(File);
-  C.reply(json::ary(
-      replacementsToEdits(Code, Server.formatOnType(File, Params.position))));
+  auto ReplacementsOrError = Server.formatOnType(Code, File, Params.position);
+  if (ReplacementsOrError)
+    C.reply(json::ary(replacementsToEdits(Code, ReplacementsOrError.get())));
+  else
+    C.replyError(ErrorCode::UnknownErrorCode,
+                 llvm::toString(ReplacementsOrError.takeError()));
 }
 
 void ClangdLSPServer::onDocumentRangeFormatting(
     Ctx C, DocumentRangeFormattingParams &Params) {
   auto File = Params.textDocument.uri.file;
   std::string Code = Server.getDocument(File);
-  C.reply(json::ary(
-      replacementsToEdits(Code, Server.formatRange(File, Params.range))));
+  auto ReplacementsOrError = Server.formatRange(Code, File, Params.range);
+  if (ReplacementsOrError)
+    C.reply(json::ary(replacementsToEdits(Code, ReplacementsOrError.get())));
+  else
+    C.replyError(ErrorCode::UnknownErrorCode,
+                 llvm::toString(ReplacementsOrError.takeError()));
 }
 
 void ClangdLSPServer::onDocumentFormatting(Ctx C,
                                            DocumentFormattingParams &Params) {
   auto File = Params.textDocument.uri.file;
   std::string Code = Server.getDocument(File);
-  C.reply(json::ary(replacementsToEdits(Code, Server.formatFile(File))));
+  auto ReplacementsOrError = Server.formatFile(Code, File);
+  if (ReplacementsOrError)
+    C.reply(json::ary(replacementsToEdits(Code, ReplacementsOrError.get())));
+  else
+    C.replyError(ErrorCode::UnknownErrorCode,
+                 llvm::toString(ReplacementsOrError.takeError()));
 }
 
 void ClangdLSPServer::onCodeAction(Ctx C, CodeActionParams &Params) {

Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=320524&r1=320523&r2=320524&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Tue Dec 12 12:25:06 2017
@@ -38,16 +38,6 @@ private:
   std::promise<void> &Promise;
 };
 
-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);
-
-  return std::vector<tooling::Replacement>(Result.begin(), Result.end());
-}
-
 std::string getStandardResourceDir() {
   static int Dummy; // Just an address in this process.
   return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);
@@ -331,26 +321,23 @@ ClangdServer::signatureHelp(PathRef File
   return make_tagged(std::move(Result), TaggedFS.Tag);
 }
 
-std::vector<tooling::Replacement> ClangdServer::formatRange(PathRef File,
-                                                            Range Rng) {
-  std::string Code = getDocument(File);
-
+llvm::Expected<tooling::Replacements>
+ClangdServer::formatRange(StringRef Code, PathRef File, Range Rng) {
   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<tooling::Replacements> ClangdServer::formatFile(StringRef Code,
+                                                               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<tooling::Replacements>
+ClangdServer::formatOnType(StringRef Code, PathRef File, Position Pos) {
   // Look for the previous opening brace from the character position and
   // format starting from there.
-  std::string Code = getDocument(File);
   size_t CursorPos = positionToOffset(Code, Pos);
   size_t PreviousLBracePos = StringRef(Code).find_last_of('{', CursorPos);
   if (PreviousLBracePos == StringRef::npos)
@@ -509,6 +496,20 @@ llvm::Optional<Path> ClangdServer::switc
   return llvm::None;
 }
 
+llvm::Expected<tooling::Replacements>
+ClangdServer::formatCode(llvm::StringRef Code, PathRef File,
+                         ArrayRef<tooling::Range> Ranges) {
+  // Call clang-format.
+  auto TaggedFS = FSProvider.getTaggedFileSystem(File);
+  auto StyleOrError =
+      format::getStyle("file", File, "LLVM", Code, TaggedFS.Value.get());
+  if (!StyleOrError) {
+    return StyleOrError.takeError();
+  } else {
+    return format::reformat(StyleOrError.get(), Code, Ranges, File);
+  }
+}
+
 llvm::Expected<Tagged<std::vector<DocumentHighlight>>>
 ClangdServer::findDocumentHighlights(PathRef File, Position Pos) {
   auto FileContents = DraftMgr.getDraft(File);

Modified: clang-tools-extra/trunk/clangd/ClangdServer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=320524&r1=320523&r2=320524&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.h Tue Dec 12 12:25:06 2017
@@ -289,12 +289,19 @@ public:
   llvm::Expected<Tagged<std::vector<DocumentHighlight>>>
   findDocumentHighlights(PathRef File, Position Pos);
 
-  /// Run formatting for \p Rng inside \p File.
-  std::vector<tooling::Replacement> formatRange(PathRef File, Range Rng);
-  /// Run formatting for the whole \p File.
-  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);
+  /// Run formatting for \p Rng inside \p File with content \p Code.
+  llvm::Expected<tooling::Replacements> formatRange(StringRef Code,
+                                                    PathRef File, Range Rng);
+
+  /// Run formatting for the whole \p File with content \p Code.
+  llvm::Expected<tooling::Replacements> formatFile(StringRef Code,
+                                                   PathRef File);
+
+  /// Run formatting after a character was typed at \p Pos in \p File with
+  /// content \p Code.
+  llvm::Expected<tooling::Replacements>
+  formatOnType(StringRef Code, PathRef File, Position Pos);
+
   /// Rename all occurrences of the symbol at the \p Pos in \p File to
   /// \p NewName.
   Expected<std::vector<tooling::Replacement>> rename(PathRef File, Position Pos,
@@ -314,6 +321,13 @@ public:
   void onFileEvent(const DidChangeWatchedFilesParams &Params);
 
 private:
+
+  /// FIXME: This stats several files to find a .clang-format file. I/O can be
+  /// slow. Think of a way to cache this.
+  llvm::Expected<tooling::Replacements>
+  formatCode(llvm::StringRef Code, PathRef File,
+             ArrayRef<tooling::Range> Ranges);
+
   std::future<void>
   scheduleReparseAndDiags(PathRef File, VersionedDraft Contents,
                           std::shared_ptr<CppFile> Resources,




More information about the cfe-commits mailing list