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, _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits