Index: clangd/ClangdLSPServer.h =================================================================== --- clangd/ClangdLSPServer.h +++ clangd/ClangdLSPServer.h @@ -73,6 +73,12 @@ std::vector getFixIts(StringRef File, const clangd::Diagnostic &D); + void replyWithTextEditsOrError( + Ctx C, std::string Code, + llvm::Expected> + ReplacementsOrError, + llvm::StringRef MessageInCaseError) const; + 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,7 @@ #include "ClangdLSPServer.h" #include "JSONRPCDispatcher.h" +#include using namespace clang::clangd; using namespace clang; @@ -89,30 +90,40 @@ Server.removeDocument(Params.textDocument.uri.file); } +void ClangdLSPServer::replyWithTextEditsOrError( + Ctx C, std::string Code, + llvm::Expected> + ReplacementsOrError, + llvm::StringRef MessageInCaseError) const { + if (!ReplacementsOrError) { + C.replyError(/*UnknownErrorCode*/ -32001, MessageInCaseError); + } else { + C.reply("[" + replacementsToEdits(Code, ReplacementsOrError.get()) + "]"); + } +} + 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; + replyWithTextEditsOrError(std::move(C), Server.getDocument(File), + Server.formatOnType(File, Params.position), + "Could not find .clang-format file!"); } 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; + replyWithTextEditsOrError(std::move(C), Server.getDocument(File), + Server.formatRange(File, Params.range), + "Could not find .clang-format file!"); } 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; + replyWithTextEditsOrError(std::move(C), Server.getDocument(File), + Server.formatFile(File), + "Could not find .clang-format file!"); } void ClangdLSPServer::onCodeAction(Ctx C, CodeActionParams &Params) { Index: clangd/ClangdServer.h =================================================================== --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -285,11 +285,15 @@ llvm::Optional switchSourceHeader(PathRef Path); /// Run formatting for \p Rng inside \p File. - std::vector formatRange(PathRef File, Range Rng); + llvm::Expected> formatRange(PathRef File, + Range Rng); + /// Run formatting for the whole \p File. - std::vector formatFile(PathRef File); + llvm::Expected> formatFile(PathRef File); + /// Run formatting after a character was typed at \p Pos in \p File. - std::vector formatOnType(PathRef File, Position Pos); + llvm::Expected> 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 &Promise; }; -std::vector formatCode(StringRef Code, StringRef Filename, - ArrayRef Ranges) { +llvm::Expected> +formatCode(StringRef Code, StringRef Filename, + ArrayRef 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"); + if (!StyleOrError) + return StyleOrError.takeError(); + auto Result = format::reformat(StyleOrError.get(), Code, Ranges, Filename); return std::vector(Result.begin(), Result.end()); } @@ -301,8 +302,8 @@ return make_tagged(std::move(Result), TaggedFS.Tag); } -std::vector ClangdServer::formatRange(PathRef File, - Range Rng) { +llvm::Expected> +ClangdServer::formatRange(PathRef File, Range Rng) { std::string Code = getDocument(File); size_t Begin = positionToOffset(Code, Rng.start); @@ -310,14 +311,15 @@ return formatCode(Code, File, {tooling::Range(Begin, Len)}); } -std::vector ClangdServer::formatFile(PathRef File) { +llvm::Expected> +ClangdServer::formatFile(PathRef File) { // Format everything. std::string Code = getDocument(File); return formatCode(Code, File, {tooling::Range(0, Code.size())}); } -std::vector ClangdServer::formatOnType(PathRef File, - Position Pos) { +llvm::Expected> +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);