xref: /llvm-project/clang-tools-extra/clangd/unittests/PrintASTTests.cpp (revision 4d006520b8c0cc3a52913b4665bf741c737e5592)
1 //===--- PrintASTTests.cpp ----------------------------------------- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "AST.h"
10 #include "Annotations.h"
11 #include "Protocol.h"
12 #include "SourceCode.h"
13 #include "TestTU.h"
14 #include "clang/AST/RecursiveASTVisitor.h"
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
17 
18 namespace clang {
19 namespace clangd {
20 namespace {
21 
22 using ::testing::ElementsAreArray;
23 
24 struct Case {
25   const char *AnnotatedCode;
26   std::vector<const char *> Expected;
27 };
28 class ASTUtils : public ::testing::Test,
29                  public ::testing::WithParamInterface<Case> {};
30 
TEST_P(ASTUtils,PrintTemplateArgs)31 TEST_P(ASTUtils, PrintTemplateArgs) {
32   auto Pair = GetParam();
33   Annotations Test(Pair.AnnotatedCode);
34   auto AST = TestTU::withCode(Test.code()).build();
35   struct Visitor : RecursiveASTVisitor<Visitor> {
36     Visitor(std::vector<Position> Points) : Points(std::move(Points)) {}
37     bool VisitNamedDecl(const NamedDecl *ND) {
38       if (TemplateArgsAtPoints.size() == Points.size())
39         return true;
40       auto Pos = sourceLocToPosition(ND->getASTContext().getSourceManager(),
41                                      ND->getLocation());
42       if (Pos != Points[TemplateArgsAtPoints.size()])
43         return true;
44       TemplateArgsAtPoints.push_back(printTemplateSpecializationArgs(*ND));
45       return true;
46     }
47     std::vector<std::string> TemplateArgsAtPoints;
48     const std::vector<Position> Points;
49   };
50   Visitor V(Test.points());
51   V.TraverseDecl(AST.getASTContext().getTranslationUnitDecl());
52   EXPECT_THAT(V.TemplateArgsAtPoints, ElementsAreArray(Pair.Expected));
53 }
54 
55 INSTANTIATE_TEST_SUITE_P(ASTUtilsTests, ASTUtils,
56                          ::testing::ValuesIn(std::vector<Case>({
57                              {
58                                  R"cpp(
59                                   template <class X> class Bar {};
60                                   template <> class ^Bar<double> {};)cpp",
61                                  {"<double>"}},
62                              {
63                                  R"cpp(
64                                   template <class X> class Bar {};
65                                   template <class T, class U,
66                                   template<typename> class Z, int Q>
67                                   struct Foo {};
68                                   template struct ^Foo<int, bool, Bar, 8>;
69                                   template <typename T>
70                                   struct ^Foo<T *, T, Bar, 3> {};)cpp",
71                                  {"<int, bool, Bar, 8>", "<T *, T, Bar, 3>"}},
72                              {
73                                  R"cpp(
74                                   template <int ...> void Foz() {};
75                                   template <> void ^Foz<3, 5, 8>() {};)cpp",
76                                  {"<3, 5, 8>"}},
77                              {
78                                  R"cpp(
79                                   template <class X> class Bar {};
80                                   template <template <class> class ...>
81                                   class Aux {};
82                                   template <> class ^Aux<Bar, Bar> {};
83                                   template <template <class> class T>
84                                   class ^Aux<T, T> {};)cpp",
85                                  {"<Bar, Bar>", "<T, T>"}},
86                              {
87                                  R"cpp(
88                                   template <typename T> T var = 1234;
89                                   template <> int ^var<int> = 1;)cpp",
90                                  {"<int>"}},
91                              {
92                                  R"cpp(
93                                   template <typename T> struct Foo;
94                                   struct Bar { friend class Foo<int>; };
95                                   template <> struct ^Foo<int> {};)cpp",
96                                  {"<int>"}},
97                              {
98                                  R"cpp(
99                                   template<class T>
100                                   T S = T(10);
101                                   template <class T>
102                                   int ^S<T*> = 0;
103                                   template <>
104                                   int ^S<double> = 0;)cpp",
105                                  {"<T *>", "<double>"}},
106                          })));
107 } // namespace
108 } // namespace clangd
109 } // namespace clang
110