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

Reply via email to