kbobyrev created this revision. kbobyrev added a reviewer: sammccall. Herald added subscribers: cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay, ilya-biryukov. Herald added a project: clang.
This patch introduces basic textDocument/foldingRange support. It relies on textDocument/documentSymbols to collect all symbols and uses takes ranges to create folds. The next steps for textDocument/foldingRange support would be: - Implementing FoldingRangeClientCapabilities and respecting respect client preferences - Specifying folding range kind - Supporting more folding range types: PP definitions, sequential includes, public/private/protected sections of classes and structs Tested: (Neo)Vim (coc-clangd) and VSCode. Related issue: https://github.com/clangd/clangd/issues/310 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D82436 Files: clang-tools-extra/clangd/ClangdLSPServer.cpp clang-tools-extra/clangd/ClangdLSPServer.h clang-tools-extra/clangd/ClangdServer.cpp clang-tools-extra/clangd/ClangdServer.h clang-tools-extra/clangd/FindSymbols.cpp clang-tools-extra/clangd/FindSymbols.h clang-tools-extra/clangd/Protocol.cpp clang-tools-extra/clangd/Protocol.h clang-tools-extra/clangd/test/initialize-params.test
Index: clang-tools-extra/clangd/test/initialize-params.test =================================================================== --- clang-tools-extra/clangd/test/initialize-params.test +++ clang-tools-extra/clangd/test/initialize-params.test @@ -37,6 +37,7 @@ # CHECK-NEXT: "clangd.applyTweak" # CHECK-NEXT: ] # CHECK-NEXT: }, +# CHECK-NEXT: "foldingRangeProvider": true, # CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "referencesProvider": true, # CHECK-NEXT: "renameProvider": true, Index: clang-tools-extra/clangd/Protocol.h =================================================================== --- clang-tools-extra/clangd/Protocol.h +++ clang-tools-extra/clangd/Protocol.h @@ -1510,6 +1510,22 @@ }; llvm::json::Value toJSON(const DocumentLink &DocumentLink); +struct FoldingRangeParams { + TextDocumentIdentifier textDocument; +}; +bool fromJSON(const llvm::json::Value &, FoldingRangeParams &); + +/// Stores information about a region of code that can be folded. +/// FIXME(kirillbobyrev): Implement FoldingRangeClientCapabilities. +struct FoldingRange { + unsigned startLine; + llvm::Optional<unsigned> startCharacter; + unsigned endLine; + llvm::Optional<unsigned> endCharacter; + llvm::Optional<std::string> kind; +}; +llvm::json::Value toJSON(const FoldingRange &Range); + } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/Protocol.cpp =================================================================== --- clang-tools-extra/clangd/Protocol.cpp +++ clang-tools-extra/clangd/Protocol.cpp @@ -1241,5 +1241,24 @@ }; } +bool fromJSON(const llvm::json::Value &Params, FoldingRangeParams &R) { + llvm::json::ObjectMapper O(Params); + return O && O.map("textDocument", R.textDocument); +} + +llvm::json::Value toJSON(const FoldingRange &Range) { + llvm::json::Object Result{ + {"startLine", Range.startLine}, + {"endLine", Range.endLine}, + }; + if (Range.startCharacter) + Result["startCharacter"] = *Range.startCharacter; + if (Range.endCharacter) + Result["endCharacter"] = *Range.endCharacter; + if (Range.kind) + Result["kind"] = *Range.kind; + return Result; +} + } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/FindSymbols.h =================================================================== --- clang-tools-extra/clangd/FindSymbols.h +++ clang-tools-extra/clangd/FindSymbols.h @@ -47,6 +47,10 @@ /// same order that they appear. llvm::Expected<std::vector<DocumentSymbol>> getDocumentSymbols(ParsedAST &AST); +/// Retrieves folding ranges using Document Symbols in the "main file" section +/// of given AST. +llvm::Expected<std::vector<FoldingRange>> getFoldingRanges(ParsedAST &AST); + } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/FindSymbols.cpp =================================================================== --- clang-tools-extra/clangd/FindSymbols.cpp +++ clang-tools-extra/clangd/FindSymbols.cpp @@ -271,11 +271,35 @@ std::vector<DocumentSymbol> collectDocSymbols(ParsedAST &AST) { return DocumentOutline(AST).build(); } + +// Recursively collects FoldingRange from a symbol and its children. +void collectFoldingRanges(DocumentSymbol Symbol, + std::vector<FoldingRange> &Result) { + FoldingRange Range; + Range.startLine = Symbol.range.start.line; + Range.startCharacter = Symbol.range.start.character; + Range.endLine = Symbol.range.end.line; + Range.endCharacter = Symbol.range.end.character; + Result.push_back(Range); + for (const auto &Child : Symbol.children) + collectFoldingRanges(Child, Result); +} } // namespace llvm::Expected<std::vector<DocumentSymbol>> getDocumentSymbols(ParsedAST &AST) { return collectDocSymbols(AST); } +// FIXME(kirillbobyrev): Collect commenets, PP definitions and other code +// regions (e.g. public/private sections of classes, control flow statement +// bodies). +llvm::Expected<std::vector<FoldingRange>> getFoldingRanges(ParsedAST &AST) { + auto DocumentSymbols = collectDocSymbols(AST); + std::vector<FoldingRange> Result; + for (const auto &Symbol : DocumentSymbols) + collectFoldingRanges(Symbol, Result); + return Result; +} + } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/ClangdServer.h =================================================================== --- clang-tools-extra/clangd/ClangdServer.h +++ clang-tools-extra/clangd/ClangdServer.h @@ -242,6 +242,9 @@ void documentSymbols(StringRef File, Callback<std::vector<DocumentSymbol>> CB); + /// Retrieve ranges that can be used to fold code within the specified file. + void foldingRanges(StringRef File, Callback<std::vector<FoldingRange>> CB); + /// Retrieve locations for symbol references. void findReferences(PathRef File, Position Pos, uint32_t Limit, Callback<ReferencesResult> CB); Index: clang-tools-extra/clangd/ClangdServer.cpp =================================================================== --- clang-tools-extra/clangd/ClangdServer.cpp +++ clang-tools-extra/clangd/ClangdServer.cpp @@ -655,6 +655,18 @@ TUScheduler::InvalidateOnUpdate); } +void ClangdServer::foldingRanges(llvm::StringRef File, + Callback<std::vector<FoldingRange>> CB) { + auto Action = + [CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable { + if (!InpAST) + return CB(InpAST.takeError()); + CB(clangd::getFoldingRanges(InpAST->AST)); + }; + WorkScheduler.runWithAST("foldingRanges", File, std::move(Action), + TUScheduler::InvalidateOnUpdate); +} + void ClangdServer::findReferences(PathRef File, Position Pos, uint32_t Limit, Callback<ReferencesResult> CB) { auto Action = [Pos, Limit, CB = std::move(CB), Index: clang-tools-extra/clangd/ClangdLSPServer.h =================================================================== --- clang-tools-extra/clangd/ClangdLSPServer.h +++ clang-tools-extra/clangd/ClangdLSPServer.h @@ -87,6 +87,7 @@ // otherwise. void onDocumentSymbol(const DocumentSymbolParams &, Callback<llvm::json::Value>); + void onFoldingRange(const FoldingRangeParams &, Callback<llvm::json::Value>); void onCodeAction(const CodeActionParams &, Callback<llvm::json::Value>); void onCompletion(const CompletionParams &, Callback<CompletionList>); void onSignatureHelp(const TextDocumentPositionParams &, Index: clang-tools-extra/clangd/ClangdLSPServer.cpp =================================================================== --- clang-tools-extra/clangd/ClangdLSPServer.cpp +++ clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -620,6 +620,7 @@ {"renameProvider", std::move(RenameProvider)}, {"selectionRangeProvider", true}, {"documentSymbolProvider", true}, + {"foldingRangeProvider", true}, {"workspaceSymbolProvider", true}, {"referencesProvider", true}, {"executeCommandProvider", @@ -922,7 +923,6 @@ static std::vector<SymbolInformation> flattenSymbolHierarchy(llvm::ArrayRef<DocumentSymbol> Symbols, const URIForFile &FileURI) { - std::vector<SymbolInformation> Results; std::function<void(const DocumentSymbol &, llvm::StringRef)> Process = [&](const DocumentSymbol &S, llvm::Optional<llvm::StringRef> ParentName) { @@ -961,6 +961,19 @@ }); } +void ClangdLSPServer::onFoldingRange(const FoldingRangeParams &Params, + Callback<llvm::json::Value> Reply) { + URIForFile FileURI = Params.textDocument.uri; + Server->foldingRanges( + Params.textDocument.uri.file(), + [FileURI, Reply = std::move(Reply)]( + llvm::Expected<std::vector<FoldingRange>> Items) mutable { + if (!Items) + return Reply(Items.takeError()); + return Reply(std::move(*Items)); + }); +} + static llvm::Optional<Command> asCommand(const CodeAction &Action) { Command Cmd; if (Action.command && Action.edit) @@ -1372,6 +1385,7 @@ MsgHandler->bind("textDocument/rename", &ClangdLSPServer::onRename); MsgHandler->bind("textDocument/hover", &ClangdLSPServer::onHover); MsgHandler->bind("textDocument/documentSymbol", &ClangdLSPServer::onDocumentSymbol); + MsgHandler->bind("textDocument/foldingRange", &ClangdLSPServer::onFoldingRange); MsgHandler->bind("workspace/executeCommand", &ClangdLSPServer::onCommand); MsgHandler->bind("textDocument/documentHighlight", &ClangdLSPServer::onDocumentHighlight); MsgHandler->bind("workspace/symbol", &ClangdLSPServer::onWorkspaceSymbol);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits