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