This revision was automatically updated to reflect the committed changes.
Closed by commit rGa11ec00afea3: FoldingRanges: Handle LineFoldingsOnly 
clients. (authored by usaxena95).

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/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() {\
@@ -336,36 +336,123 @@
         ]]};
       )cpp",
       R"cpp(
-        [[/* Multi 
+        /*[[ Multi 
           * line
           *  comment 
-          */]]
+          ]]*/
       )cpp",
       R"cpp(
-        [[// Comment
+        //[[ Comment
         // 1]]
         
-        [[// Comment
+        //[[ Comment
         // 2]]
         
         // No folding for single line comment.
 
-        [[/* comment 3
-        */]]
+        /*[[ comment 3
+        ]]*/
 
-        [[/* comment 4
-        */]]
+        /*[[ comment 4
+        ]]*/
+
+        /*[[ foo */
+        /* bar ]]*/
+
+        /*[[ foo */
+        // baz
+        /* bar ]]*/
+
+        /*[[ foo */
+        /* bar*/
+        // baz]]
+
+        //[[ foo
+        /* bar */]]
       )cpp",
   };
   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) {[[
+            a++;]]
+        }
+      )cpp",
+      R"cpp(
+        // Always exclude last line for brackets.
+        void func(int a) {[[
+          if(a == 1) {[[
+            a++;]]
+          } else if (a == 2){[[
+            a--;]]
+          } else {  // No folding for 2 line bracketed ranges.
+          }]]
+        }
+      )cpp",
+      R"cpp(
+        /*[[ comment
+        * comment]]
+        */
+
+        /* No folding for this comment.
+        */
+
+        // No folding for this comment.
+
+        //[[ 2 single line comment.
+        // 2 single line comment.]]
+
+        //[[ >=2 line comments.
+        // >=2 line comments.
+        // >=2 line comments.]]
+
+        //[[ foo\
+        bar\
+        baz]]
+
+        /*[[ foo */
+        /* bar */]]
+        /* baz */
+
+        /*[[ foo */
+        /* bar]]
+        * This does not fold me */
+
+        //[[ foo
+        /* bar */]]
+      )cpp",
+      // FIXME: Support folding template arguments.
+      // R"cpp(
+      // template <[[typename foo, class bar]]> struct baz {};
+      // )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(
+        StripColumns(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 LineFoldingOnly);
 
 } // 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 LineFoldingOnly) {
   auto OrigStream = pseudo::lex(Code, clang::pseudo::genericLangOpts());
 
   auto DirectiveStructure = pseudo::DirectiveTree::parse(OrigStream);
@@ -192,15 +192,17 @@
   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;
     FR.kind = Kind.str();
-    return FR;
+    Result.push_back(FR);
   };
   auto OriginalToken = [&](const pseudo::Token &T) {
     return OrigStream.tokens()[T.OriginalIndex];
@@ -211,8 +213,11 @@
   auto StartPosition = [&](const pseudo::Token &T) {
     return offsetToPosition(Code, StartOffset(T));
   };
+  auto EndOffset = [&](const pseudo::Token &T) {
+    return StartOffset(T) + OriginalToken(T).Length;
+  };
   auto EndPosition = [&](const pseudo::Token &T) {
-    return offsetToPosition(Code, StartOffset(T) + OriginalToken(T).Length);
+    return offsetToPosition(Code, EndOffset(T));
   };
   auto Tokens = ParseableStream.tokens();
   // Brackets.
@@ -223,26 +228,43 @@
       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));
+        if (LineFoldingOnly)
+          End.line--;
+        AddFoldingRange(Start, End, FoldingRange::REGION_KIND);
       }
     }
   }
+  auto IsBlockComment = [&](const pseudo::Token &T) {
+    assert(T.Kind == tok::comment);
+    return OriginalToken(T).Length >= 2 &&
+           Code.substr(StartOffset(T), 2) == "/*";
+  };
   // Multi-line comments.
-  for (const auto *T = Tokens.begin(); T != Tokens.end();) {
+  for (auto *T = Tokens.begin(); T != Tokens.end();) {
     if (T->Kind != tok::comment) {
       T++;
       continue;
     }
-    Position Start = StartPosition(*T);
-    Position LastCommentEnd = EndPosition(*T);
+    pseudo::Token *FirstComment = T;
+    // Show starting sentinals (// and /*) of the comment.
+    Position Start = offsetToPosition(Code, 2 + StartOffset(*FirstComment));
+    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));
+    if (IsBlockComment(*FirstComment)) {
+      if (LineFoldingOnly)
+        // Show last line of a block comment.
+        End.line--;
+      if (IsBlockComment(*LastComment))
+        // Show ending sentinal "*/" of the block comment.
+        End.character -= 2;
+    }
+    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
@@ -437,6 +437,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,10 @@
         }
       }
     }
+    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
@@ -164,6 +164,9 @@
     /// Enable preview of FoldingRanges feature.
     bool FoldingRanges = false;
 
+    // Whether the client supports folding only complete lines.
+    bool LineFoldingOnly = false;
+
     FeatureModuleSet *FeatureModules = nullptr;
     /// If true, use the dirty buffer contents when building Preambles.
     bool UseDirtyHeaders = false;
@@ -429,6 +432,9 @@
 
   bool UseDirtyHeaders = false;
 
+  // Whether the client supports folding only complete lines.
+  bool LineFoldingOnly = false;
+
   bool PreambleParseForwardingFunctions = false;
 
   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
Index: clang-tools-extra/clangd/ClangdServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -177,6 +177,7 @@
       DynamicIdx(Opts.BuildDynamicSymbolIndex ? new FileIndex() : nullptr),
       ClangTidyProvider(Opts.ClangTidyProvider),
       UseDirtyHeaders(Opts.UseDirtyHeaders),
+      LineFoldingOnly(Opts.LineFoldingOnly),
       PreambleParseForwardingFunctions(Opts.PreambleParseForwardingFunctions),
       WorkspaceRoot(Opts.WorkspaceRoot),
       Transient(Opts.ImplicitCancellation ? TUScheduler::InvalidateOnUpdate
@@ -855,8 +856,9 @@
     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 = [LineFoldingOnly = LineFoldingOnly, CB = std::move(CB),
+                 Code = std::move(*Code)]() mutable {
+    CB(clangd::getFoldingRanges(Code, LineFoldingOnly));
   };
   // 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.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -514,6 +514,7 @@
       Params.capabilities.HierarchicalDocumentSymbol;
   SupportFileStatus = Params.initializationOptions.FileStatus;
   HoverContentFormat = Params.capabilities.HoverContentFormat;
+  Opts.LineFoldingOnly = Params.capabilities.LineFoldingOnly;
   SupportsOffsetsInSignatureHelp = Params.capabilities.OffsetsInSignatureHelp;
   if (Params.capabilities.WorkDoneProgress)
     BackgroundIndexProgressState = BackgroundIndexProgress::Empty;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to