usaxena95 updated this revision to Diff 449931. usaxena95 added a comment. More tests.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D131154/new/ https://reviews.llvm.org/D131154 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/Protocol.cpp clang-tools-extra/clangd/Protocol.h clang-tools-extra/clangd/SemanticSelection.cpp clang-tools-extra/clangd/SemanticSelection.h clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp +++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp @@ -196,7 +196,7 @@ ElementsAre(SourceAnnotations.range("empty"))); } -TEST(FoldingRanges, All) { +TEST(FoldingRanges, ASTAll) { const char *Tests[] = { R"cpp( #define FOO int foo() {\ @@ -265,7 +265,7 @@ } } -TEST(FoldingRangesPseudoParser, All) { +TEST(FoldingRanges, PseudoParserWithoutLineFoldings) { const char *Tests[] = { R"cpp( #define FOO int foo() {\ @@ -359,13 +359,55 @@ }; for (const char *Test : Tests) { auto T = Annotations(Test); - EXPECT_THAT( - gatherFoldingRanges(llvm::cantFail(getFoldingRanges(T.code().str()))), - UnorderedElementsAreArray(T.ranges())) + EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges( + T.code().str(), /*LineFoldingsOnly=*/false))), + UnorderedElementsAreArray(T.ranges())) << Test; } } +TEST(FoldingRanges, PseudoParserLineFoldingsOnly) { + const char *Tests[] = { + R"cpp( + void func(int a) {[[ + if(a == 1) {[[ + a++;]] + } else {[[ + a--; + /*tokens inside foldings are fine.*/ ]]} + ]]} + )cpp", + R"cpp( + void func(int a) {[[ + a++;]] + } // A token on the end line. + )cpp", + R"cpp( + [[/* comment 1 + * comment 1]] + */ int a_token = 0; + + /* No folding for this comment. + */ int b_token=0; + )cpp", + + }; + auto StripColumns = [](const std::vector<Range> &Ranges) { + std::vector<Range> Res; + for (Range R : Ranges) { + R.start.character = R.end.character = 0; + Res.push_back(R); + } + return Res; + }; + for (const char *Test : Tests) { + auto T = Annotations(Test); + EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges( + T.code().str(), /*LineFoldingsOnly=*/true))), + UnorderedElementsAreArray(StripColumns(T.ranges()))) + << Test; + } +} } // namespace } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/SemanticSelection.h =================================================================== --- clang-tools-extra/clangd/SemanticSelection.h +++ clang-tools-extra/clangd/SemanticSelection.h @@ -33,7 +33,7 @@ /// Returns a list of ranges whose contents might be collapsible in an editor. /// This version uses the pseudoparser which does not require the AST. llvm::Expected<std::vector<FoldingRange>> -getFoldingRanges(const std::string &Code); +getFoldingRanges(const std::string &Code, bool LineFoldingsOnly); } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/SemanticSelection.cpp =================================================================== --- clang-tools-extra/clangd/SemanticSelection.cpp +++ clang-tools-extra/clangd/SemanticSelection.cpp @@ -179,7 +179,7 @@ // statement bodies). // Related issue: https://github.com/clangd/clangd/issues/310 llvm::Expected<std::vector<FoldingRange>> -getFoldingRanges(const std::string &Code) { +getFoldingRanges(const std::string &Code, bool LineFoldingsOnly) { auto OrigStream = pseudo::lex(Code, clang::pseudo::genericLangOpts()); auto DirectiveStructure = pseudo::DirectiveTree::parse(OrigStream); @@ -192,15 +192,21 @@ pseudo::pairBrackets(ParseableStream); std::vector<FoldingRange> Result; - auto ToFoldingRange = [](Position Start, Position End, - llvm::StringLiteral Kind) { + auto AddFoldingRange = [&](Position Start, Position End, + llvm::StringLiteral Kind) { + if (Start.line >= End.line) + return; FoldingRange FR; FR.startLine = Start.line; - FR.startCharacter = Start.character; FR.endLine = End.line; - FR.endCharacter = End.character; + if (LineFoldingsOnly) + FR.startCharacter = FR.endCharacter = 0; + else { + FR.startCharacter = Start.character; + FR.endCharacter = End.character; + } FR.kind = Kind.str(); - return FR; + Result.push_back(FR); }; auto OriginalToken = [&](const pseudo::Token &T) { return OrigStream.tokens()[T.OriginalIndex]; @@ -214,6 +220,17 @@ auto EndPosition = [&](const pseudo::Token &T) { return offsetToPosition(Code, StartOffset(T) + OriginalToken(T).Length); }; + auto AdjustForLineFoldingsOnly = [&](const pseudo::Token &EndToken, + Position End) { + // For LineFoldingsOnly clients, do not fold the last line if it + // contains tokens after `End`. + if (LineFoldingsOnly && + EndToken.OriginalIndex + 1 < OrigStream.tokens().size() && + End.line == + StartPosition(OrigStream.tokens()[EndToken.OriginalIndex + 1]).line) + End.line--; + return End; + }; auto Tokens = ParseableStream.tokens(); // Brackets. for (const auto &Tok : Tokens) { @@ -221,9 +238,10 @@ // Process only token at the start of the range. Avoid ranges on a single // line. if (Tok.Line < Paired->Line) { - Position Start = offsetToPosition(Code, 1 + StartOffset(Tok)); - Position End = StartPosition(*Paired); - Result.push_back(ToFoldingRange(Start, End, FoldingRange::REGION_KIND)); + const Position Start = offsetToPosition(Code, 1 + StartOffset(Tok)); + const Position End = + AdjustForLineFoldingsOnly(*Paired, StartPosition(*Paired)); + AddFoldingRange(Start, End, FoldingRange::REGION_KIND); } } } @@ -233,16 +251,17 @@ T++; continue; } - Position Start = StartPosition(*T); - Position LastCommentEnd = EndPosition(*T); + const Position Start = StartPosition(*T); + const pseudo::Token *LastComment = T; + Position End = EndPosition(*T); while (T != Tokens.end() && T->Kind == tok::comment && - StartPosition(*T).line <= LastCommentEnd.line + 1) { - LastCommentEnd = EndPosition(*T); + StartPosition(*T).line <= End.line + 1) { + End = EndPosition(*T); + LastComment = T; T++; } - if (Start.line < LastCommentEnd.line) - Result.push_back( - ToFoldingRange(Start, LastCommentEnd, FoldingRange::COMMENT_KIND)); + End = AdjustForLineFoldingsOnly(*LastComment, End); + AddFoldingRange(Start, End, FoldingRange::COMMENT_KIND); } return Result; } Index: clang-tools-extra/clangd/Protocol.h =================================================================== --- clang-tools-extra/clangd/Protocol.h +++ clang-tools-extra/clangd/Protocol.h @@ -434,6 +434,12 @@ /// textDocument.signatureHelp bool HasSignatureHelp = false; + /// Client signals that it only supports folding complete lines. + /// Client will ignore specified `startCharacter` and `endCharacter` + /// properties in a FoldingRange. + /// textDocument.foldingRange.lineFoldingOnly + bool LineFoldingOnly = false; + /// Client supports processing label offsets instead of a simple label string. /// textDocument.signatureHelp.signatureInformation.parameterInformation.labelOffsetSupport bool OffsetsInSignatureHelp = false; Index: clang-tools-extra/clangd/Protocol.cpp =================================================================== --- clang-tools-extra/clangd/Protocol.cpp +++ clang-tools-extra/clangd/Protocol.cpp @@ -391,6 +391,11 @@ } } } + if (auto *Folding = TextDocument->getObject("foldingRange")) { + if (auto LineFolding = Folding->getBoolean("lineFoldingOnly")) { + R.LineFoldingOnly = *LineFolding; + } + } if (auto *Rename = TextDocument->getObject("rename")) { if (auto RenameSupport = Rename->getBoolean("prepareSupport")) R.RenamePrepareSupport = *RenameSupport; Index: clang-tools-extra/clangd/ClangdServer.h =================================================================== --- clang-tools-extra/clangd/ClangdServer.h +++ clang-tools-extra/clangd/ClangdServer.h @@ -281,7 +281,8 @@ 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); + void foldingRanges(StringRef File, bool LineFoldingsOnly, + Callback<std::vector<FoldingRange>> CB); /// Retrieve implementations for virtual method. void findImplementations(PathRef File, Position Pos, Index: clang-tools-extra/clangd/ClangdServer.cpp =================================================================== --- clang-tools-extra/clangd/ClangdServer.cpp +++ clang-tools-extra/clangd/ClangdServer.cpp @@ -832,15 +832,16 @@ Transient); } -void ClangdServer::foldingRanges(llvm::StringRef File, +void ClangdServer::foldingRanges(llvm::StringRef File, bool LineFoldingsOnly, Callback<std::vector<FoldingRange>> CB) { auto Code = getDraft(File); if (!Code) return CB(llvm::make_error<LSPError>( "trying to compute folding ranges for non-added document", ErrorCode::InvalidParams)); - auto Action = [CB = std::move(CB), Code = std::move(*Code)]() mutable { - CB(clangd::getFoldingRanges(Code)); + auto Action = [LineFoldingsOnly, CB = std::move(CB), + Code = std::move(*Code)]() mutable { + CB(clangd::getFoldingRanges(Code, LineFoldingsOnly)); }; // We want to make sure folding ranges are always available for all the open // files, hence prefer runQuick to not wait for operations on other files. Index: clang-tools-extra/clangd/ClangdLSPServer.h =================================================================== --- clang-tools-extra/clangd/ClangdLSPServer.h +++ clang-tools-extra/clangd/ClangdLSPServer.h @@ -259,6 +259,8 @@ MarkupKind HoverContentFormat = MarkupKind::PlainText; /// Whether the client supports offsets for parameter info labels. bool SupportsOffsetsInSignatureHelp = false; + // Whether the client supports folding only complete lines. + bool LineFoldingsOnly = false; std::mutex BackgroundIndexProgressMutex; enum class BackgroundIndexProgress { // Client doesn't support reporting progress. No transitions possible. Index: clang-tools-extra/clangd/ClangdLSPServer.cpp =================================================================== --- clang-tools-extra/clangd/ClangdLSPServer.cpp +++ clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -512,6 +512,7 @@ Params.capabilities.HierarchicalDocumentSymbol; SupportFileStatus = Params.initializationOptions.FileStatus; HoverContentFormat = Params.capabilities.HoverContentFormat; + LineFoldingsOnly = Params.capabilities.LineFoldingOnly; SupportsOffsetsInSignatureHelp = Params.capabilities.OffsetsInSignatureHelp; if (Params.capabilities.WorkDoneProgress) BackgroundIndexProgressState = BackgroundIndexProgress::Empty; @@ -939,7 +940,8 @@ void ClangdLSPServer::onFoldingRange( const FoldingRangeParams &Params, Callback<std::vector<FoldingRange>> Reply) { - Server->foldingRanges(Params.textDocument.uri.file(), std::move(Reply)); + Server->foldingRanges(Params.textDocument.uri.file(), LineFoldingsOnly, + std::move(Reply)); } static llvm::Optional<Command> asCommand(const CodeAction &Action) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits