kbobyrev updated this revision to Diff 279132.
kbobyrev marked 13 inline comments as done.
kbobyrev added a comment.

Resolve most comments, make sure everything builds.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D83914/new/

https://reviews.llvm.org/D83914

Files:
  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
@@ -234,6 +234,544 @@
   }
 }
 
+TEST(FoldingRanges, ControlFlow) {
+  const char *Tests[] = {
+      // If.
+      R"cpp(
+        int main() {[[
+          bool B = true;
+          int I = 0;
+          char C = 'z';
+
+          if (B && I > 42 || ~(++I)) {[[
+            ++I;
+          ]]} else {[[
+            B = false;
+          ]]}
+
+          if (B && (!B) || !((C == 'a'))) {[[
+            ++I;
+          ]]} else if ([[!B && true != false &&
+                       2 * 2 == 4]]) {[[
+            --I;
+          ]]} else {[[
+            C = 'a';
+          ]]}
+
+          if (B && ([["subexpression" != "multi-line" &&
+                    1 > 0]]))
+            B = false;
+
+          if ([[int Init = 0, Variable = 9000;
+              [[Init == 0 && Init > 0 ||
+              Init < 5000]]]])
+            Init = 42;
+        ]]}
+      )cpp",
+      // While.
+      R"cpp(
+        int main() {[[
+          bool B;
+          while ([[B]]) {[[
+            B = !B;
+          ]]}
+
+          do {[[
+            B = !B;
+          ]]} while ([[B]]);
+        ]]}
+      )cpp",
+      // For.
+      R"cpp(
+        int main() {[[
+          for ([[int I = 0;I < 42; ++I]]) {[[
+            --I;
+          ]]}
+        ]]}
+      )cpp",
+      // Switch.
+      R"cpp(
+        void noop();
+
+        int main() {[[
+          int i = 2;
+          switch ([[i]]) {[[
+              case 1:[[ noop();]]
+              case 2:[[ noop(); //[[execution starts at this case label]]]]
+              case 3:[[ noop();]]
+              case 4:
+              case 5:[[ noop();
+                      break;              //[[execution of subsequent statements is terminated]]]]
+              case 6:[[ noop();]]
+          ]]}
+        ]]}
+      )cpp",
+  };
+  for (const char *Test : Tests) {
+    auto T = Annotations(Test);
+    auto AST = TestTU::withCode(T.code()).build();
+    EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(AST))),
+                UnorderedElementsAreArray(T.ranges()))
+        << Test;
+  }
+}
+
+TEST(FoldingRanges, Misc) {
+  const char *Tests[] = {
+      // Statement groups.
+      R"cpp(
+        int main() {[[
+          [[int X = 5;
+          int Y = 42;
+          bool B = 15;]]
+          if ([[B]]) {[[ ++X; ]]}
+          unsigned U = 9000;
+        ]]}
+      )cpp",
+      // Expressions (fold if they span multiple lines).
+      R"cpp(
+        int main() {[[
+          bool B = 42 > 0;
+          B = (42 > 0);
+          B = (42 > 0 && 9000 > 2000);
+          B = 42 > 0 && (9000 > 2000 && 2000 > 1000);
+          B = [[42 > 0 && ([[9000 > 2000 &&
+                         2000 > 1000]])]];
+        ]]}
+      )cpp",
+      // Enum.
+      R"cpp(
+        enum Color {[[
+          Green = 0,
+          YInMn,
+          Orange,
+        ]]};
+      )cpp",
+      // Argument lists.
+      R"cpp(
+        int foo([[char C, bool B]]) {[[ return static_cast<int>(C); ]]}
+
+        foo([['z', true]]);
+
+        struct Foo {
+          Foo([[int I, unsigned U, bool B=true]]) {}
+        };
+
+        Foo F = Foo([[/*[[I=]]*/1, /*[[U=]]*/2, /*[[B=]]false]]);
+        F = Foo([[1, 2]]);
+      )cpp",
+      // Namespace.
+      R"cpp(
+        namespace ns {[[
+        int Variable = 42;
+        namespace nested {[[
+        int NestedVariable = 50;
+        ]]}
+        ]]}
+
+        namespace a {[[
+        namespace b {[[
+        namespace c {[[
+
+        ]]} //[[ namespacee c]]
+        ]]} //[[ namespacee b]]
+        ]]} //[[ namespacee a]]
+
+        namespace modern::ns::syntax {[[
+        ]]} //[[ namespace modern::ns::syntax]]
+
+        namespace {[[
+        ]]} //[[ namespace]]
+
+        extern "C" {[[
+          void Foo();
+        ]]}
+      )cpp",
+      // Strings.
+      R"cpp(
+        std::string String = "[[ShortString]]";
+        String = "[[Suuuuuuuuuuuuuuuuuper Looooooooooooooooong String]]";
+        String = u8"[[Suuuuuuuuuuuuuuuuuper Looooooooooooooooong String]]";
+
+        String = R"raw([[Suuuuuuuuuuuuuuuuuper Looooooooooooooong String]])raw";
+
+        const char *text =
+          "[[This"
+          "is a multiline"
+          "string]]";
+
+        const char *text2 =
+          "[[Here is another \
+        string \
+        also \
+        multilineeeeee]]";
+      )cpp",
+      // Arrays.
+      R"cpp(
+        char Array[] = {[[ 'F', 'o', 'o', 'b', 'a', 'r', '\0' ]]};
+
+        Array = {[[ 'F', 'o', 'o', 'b', 'a', 'r', 'F', 'o', 'o', 'b',
+                 'a', 'r', '\0' ]]};
+
+        int Nested[3][4] = {[[{[[0,1,2,3]]}, {[[4,5,6,7]]}, {[[8,9,10,11]]}]]};
+      )cpp",
+      // Templates.
+      R"cpp(
+        template <[[typename T, typename U, typename V, int X, char C, bool B]]>
+        class Foo {};
+
+        template <[[bool B]]>
+        class Foo<[[unsigned, unsigned, unsigned, -42, 'z', B]]> {
+          int Specialization;
+        };
+
+        template <>
+        class Foo<[[unsigned, unsigned, unsigned, -42, 'z', false]]> {
+          int Specialization;
+        };
+
+        Foo<[[char, int, bool, 42, 'x', false]]> F;
+
+        template <[[typename T, unsigned U]]>
+        void foo([[T t, unsigned u]]) {[[ return; ]]}
+
+        template <[[unsigned U]]>
+        void foo<[U, 50]>([[char t, U u]]) {}
+
+        template <>
+        void foo<[char, 42]>([[char t, U u]]) {}
+      )cpp",
+      // Lambdas.
+      R"cpp(
+        int main() {[[
+          bool B = true;
+          int I = 42;
+          auto Lambda = [=]([[auto a, auto&& b]]) {[[ return a < b; ]]};
+          auto vglambda = [[[=, &B, &I]]]([[auto printer]]) {
+              return [=](auto&&... ts)
+              {
+                  return [=] { printer(ts...); };
+              };
+          };
+        ]]}
+      )cpp",
+  };
+  for (const char *Test : Tests) {
+    auto T = Annotations(Test);
+    auto AST = TestTU::withCode(T.code()).build();
+    EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(AST))),
+                UnorderedElementsAreArray(T.ranges()))
+        << Test;
+  }
+}
+
+TEST(FoldingRanges, Comments) {
+  const char *Tests[] = {
+      R"cpp(
+        //[[ This is a one-line comment.]]
+      )cpp",
+      R"cpp(
+        //[[ Continuous
+        // Comment
+        // ...]]
+
+        //[[ And another one
+        // But doesn't belong to the one above]]
+
+        //[[ This time
+        //
+        // It's connected!]]
+
+        ///[[ Doxygen]]
+
+        ///[[ Doxygen
+        /// With more multiple lines.
+        ///
+        ///
+        /// The End]]
+      )cpp",
+      R"cpp(
+        /*[[ C-Style comment. ]]*/
+
+        [[/* Spanning
+         * multiple
+         * lines */]]
+      )cpp",
+      R"cpp(
+        [[/* C-Style
+         * multiple
+         * lines */]]
+        //[[ Followed by C++ Style
+        // Are still different comments!]]
+      )cpp",
+      R"cpp(
+        /*[[!
+         * ... text ...
+         ]]*/
+
+        /*[[*
+         * ... text ...
+         ]]*/
+
+        /*[[!
+         ... text ...
+        ]]*/
+
+        ///[[
+        /// ... text ...
+        ///]]
+
+        //[[!
+        //!... text ...
+        //!]]
+
+        /*[[*******************************************//**
+        *  ... text
+        **********************************************]]*/
+
+        //[[///////////////////////////////////////////////
+        /// ... text ...
+        /////////////////////////////////////////////////]]
+
+        /*[[***********************************************
+         *  ... text
+         **********************************************]]*/
+      )cpp",
+      R"cpp(
+        /*[[
+          Tricky C-Style
+
+          void Foo(int I);
+          void Foo(int I, char C);
+        /*]]*/
+      )cpp",
+      R"cpp(
+        int Foo([[int I, bool Boolean=false]]) {[[
+          return 42; //[[ Do nothing, just return!]]
+        ]]}
+
+        const auto Variable = Foo([[42, /*[[Boolean=]]*/true]]);
+      )cpp",
+      R"cpp(
+        //[[ Some documentation.
+        // @param
+        int Foo([[int I, bool Boolean=false]]) {[[ //[[ With a comment]]
+          return 42; //[[ Do nothing, just return!]]
+        ]]}
+
+        const auto Variable = Foo([[42, /*[[Boolean=]]*/]]true]]);
+      )cpp",
+      R"cpp(
+        //[[ Empty comments don't generate folding ranges!]]
+
+        //
+        /**/
+        ///
+      )cpp",
+  };
+  for (const char *Test : Tests) {
+    auto T = Annotations(Test);
+    auto AST = TestTU::withCode(T.code()).build();
+    EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(AST))),
+                UnorderedElementsAreArray(T.ranges()))
+        << Test;
+  }
+}
+
+TEST(FoldingRanges, Preprocessor) {
+  const char *Tests[] = {
+      R"cpp(
+        #include [[<cmath>
+        #include <cstdio>
+        #include <iostream>]]
+
+        #include [[<vector>]]
+
+        #include [["external/Logger.h"
+        #include "external/Vector.h"
+        #include "project/DataStructures/Trie.h"]]
+
+        #include [["project/File.h"
+        #include <map>
+        #include <set>]]
+
+        #include [["math.h"]]
+      )cpp",
+      R"cpp(
+        #define true [[false]]
+
+        #define getmax(a,b) [[((a)>(b)?(a):(b))]]
+        #define PI [[3.14159]]
+      )cpp",
+      R"cpp(
+        #ifndef [[FOO_H_INCLUDED]][[ /*[[ any name uniquely mapped to file name ]]*/
+        #define FOO_H_INCLUDED
+        //[[ ^ Don't fold simple definition?]]
+
+        //[[ contents of the file are here]]
+        ]]#endif
+
+        #ifndef [[LIBRARY_FILENAME_H]][[
+        #define LIBRARY_FILENAME_H
+        //[[ contents of the header]]
+        ]]#endif /*[[ LIBRARY_FILENAME_H ]]*/
+
+        #if [[__has_include(<optional>)]][[
+        #  include <optional>
+        #  define have_optional 1
+        ]]#elif [[__has_include(<experimental/optional>)]][[
+        #  include <experimental/optional>
+        #  define have_optional 1
+        #  define experimental_optional 1
+        ]]#else[[
+        #  define have_optional 0
+        ]]#endif
+
+        #if [[OK]][[
+        # define NICE
+        ]]#else[[
+        #  define true [[false]]
+        ]]#endif
+
+        #ifdef [[SOMETHING]][[
+        //[[ Oh no!]]
+        #undef SOMETHING
+        ]]#else[[
+        #define OKAY_GOOD
+        ]]#endif
+      )cpp",
+  };
+  for (const char *Test : Tests) {
+    auto T = Annotations(Test);
+    auto AST = TestTU::withCode(T.code()).build();
+    EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(AST))),
+                UnorderedElementsAreArray(T.ranges()))
+        << Test;
+  }
+}
+
+TEST(FoldingRanges, Classes) {
+  const char *Tests[] = {
+      // Basics.
+      R"cpp(
+        class Foo {[[
+          int I;
+        ]]};
+
+        struct Bar {[[
+          int I;
+        ]]};
+
+        class Baz {[[
+        public:[[
+          Baz();
+
+          int I;]]
+        ]]};
+
+        class Chewbacca {};
+        class Vader;
+
+        struct FooStruct {[[
+          int Field;
+        ]]};
+        struct BarStruct {[[]]};
+        struct FwdDeclaration;
+      )cpp",
+      // Accessor secions.
+      R"cpp(
+        class Foo {[[
+        public:
+        private:
+        protected:
+        public:
+        ]]};
+
+        class Bar {[[
+        public:[[
+          Bar();
+          Bar([[int X]]);
+]]
+        private:[[
+          int Field;]]
+        protected:[[
+          bool ProtectThis;]]
+        public:[[
+          int getField() {[[ return Field; ]]}]]
+        ]]};
+
+        class ImplicitFirstSection {[[[[
+          ImplicitFirstSection() {}
+
+          int Field;]]
+        public:[[
+
+          int getField();]]
+        ]]};
+      )cpp",
+      // Nested classes with accessor sections.
+      R"cpp(
+        class Nested {[[
+        public:
+        private:[[
+          class Inner {[[
+          public:[[
+            Inner();
+            Inner(int X);
+  ]]
+          private:[[
+            int Field;]]
+          protected:[[
+            bool ProtectThis;]]
+          public:[[
+            int getField() {[[ return Field; ]]}]]
+          ]]};]]
+        protected:
+        public:
+        ]]};
+
+        struct NestedStruct {[[
+        public:
+        private:[[
+          class Inner {[[
+          public:[[
+            Inner();
+            Inner(int X);
+  ]]
+          private:[[
+            int Field;]]
+          protected:[[
+            bool ProtectThis;]]
+          public:[[
+            int getField() {[[ return Field; ]]}]]
+          ]]};]]
+        protected:
+        public:
+        ]]};
+      )cpp",
+      // Member initializer lists.
+      R"cpp(
+        class Foo {[[
+        public:[[
+          Foo([[int Integer, char Char, bool Boolean]]) :[[ I(Integer), C(Char), B(Boolean) ]] {[[
+            int X;
+          ]]}]]
+        private:[[
+          int I;
+          char C;
+          bool B;]]
+        ]]};
+      )cpp",
+  };
+  for (const char *Test : Tests) {
+    auto T = Annotations(Test);
+    auto AST = TestTU::withCode(T.code()).build();
+    EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(AST))),
+                UnorderedElementsAreArray(T.ranges()))
+        << Test;
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to