clang-tools  10.0.0git
ASTTests.cpp
Go to the documentation of this file.
1 //===-- ASTTests.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 
11 #include "Annotations.h"
12 #include "ParsedAST.h"
13 #include "TestTU.h"
14 #include "clang/AST/Decl.h"
15 #include "clang/AST/DeclBase.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/Casting.h"
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 #include <cstddef>
22 #include <string>
23 #include <vector>
24 
25 namespace clang {
26 namespace clangd {
27 namespace {
28 
29 TEST(GetDeducedType, KwAutoExpansion) {
30  struct Test {
31  StringRef AnnotatedCode;
32  const char *DeducedType;
33  } Tests[] = {
34  {"^auto i = 0;", "int"},
35  {"^auto f(){ return 1;};", "int"},
36  };
37  for (Test T : Tests) {
38  Annotations File(T.AnnotatedCode);
39  auto AST = TestTU::withCode(File.code()).build();
40  ASSERT_TRUE(AST.getDiagnostics().empty())
41  << AST.getDiagnostics().begin()->Message;
42  SourceManagerForFile SM("foo.cpp", File.code());
43 
44  for (Position Pos : File.points()) {
45  auto Location = sourceLocationInMainFile(SM.get(), Pos);
46  ASSERT_TRUE(!!Location) << llvm::toString(Location.takeError());
47  auto DeducedType = getDeducedType(AST.getASTContext(), *Location);
48  EXPECT_EQ(DeducedType->getAsString(), T.DeducedType);
49  }
50  }
51 }
52 
53 TEST(ClangdAST, GetQualification) {
54  // Tries to insert the decl `Foo` into position of each decl named `insert`.
55  // This is done to get an appropriate DeclContext for the insertion location.
56  // Qualifications are the required nested name specifier to spell `Foo` at the
57  // `insert`ion location.
58  // VisibleNamespaces are assumed to be visible at every insertion location.
59  const struct {
60  llvm::StringRef Test;
61  std::vector<llvm::StringRef> Qualifications;
62  std::vector<std::string> VisibleNamespaces;
63  } Cases[] = {
64  {
65  R"cpp(
66  namespace ns1 { namespace ns2 { class Foo {}; } }
67  void insert(); // ns1::ns2::Foo
68  namespace ns1 {
69  void insert(); // ns2::Foo
70  namespace ns2 {
71  void insert(); // Foo
72  }
73  using namespace ns2;
74  void insert(); // Foo
75  }
76  using namespace ns1;
77  void insert(); // ns2::Foo
78  using namespace ns2;
79  void insert(); // Foo
80  )cpp",
81  {"ns1::ns2::", "ns2::", "", "", "ns2::", ""},
82  {},
83  },
84  {
85  R"cpp(
86  namespace ns1 { namespace ns2 { class Bar { void Foo(); }; } }
87  void insert(); // ns1::ns2::Bar::Foo
88  namespace ns1 {
89  void insert(); // ns2::Bar::Foo
90  namespace ns2 {
91  void insert(); // Bar::Foo
92  }
93  using namespace ns2;
94  void insert(); // Bar::Foo
95  }
96  using namespace ns1;
97  void insert(); // ns2::Bar::Foo
98  using namespace ns2;
99  void insert(); // Bar::Foo
100  )cpp",
101  {"ns1::ns2::Bar::", "ns2::Bar::", "Bar::", "Bar::", "ns2::Bar::",
102  "Bar::"},
103  {},
104  },
105  {
106  R"cpp(
107  namespace ns1 { namespace ns2 { void Foo(); } }
108  void insert(); // ns2::Foo
109  namespace ns1 {
110  void insert(); // ns2::Foo
111  namespace ns2 {
112  void insert(); // Foo
113  }
114  }
115  )cpp",
116  {"ns2::", "ns2::", ""},
117  {"ns1::"},
118  },
119  };
120  for (const auto &Case : Cases) {
121  Annotations Test(Case.Test);
122  TestTU TU = TestTU::withCode(Test.code());
123  ParsedAST AST = TU.build();
124  std::vector<const Decl *> InsertionPoints;
125  const NamedDecl *TargetDecl;
126  findDecl(AST, [&](const NamedDecl &ND) {
127  if (ND.getNameAsString() == "Foo") {
128  TargetDecl = &ND;
129  return true;
130  }
131 
132  if (ND.getNameAsString() == "insert")
133  InsertionPoints.push_back(&ND);
134  return false;
135  });
136 
137  ASSERT_EQ(InsertionPoints.size(), Case.Qualifications.size());
138  for (size_t I = 0, E = InsertionPoints.size(); I != E; ++I) {
139  const Decl *D = InsertionPoints[I];
140  if (Case.VisibleNamespaces.empty()) {
141  EXPECT_EQ(getQualification(AST.getASTContext(),
142  D->getLexicalDeclContext(), D->getBeginLoc(),
143  TargetDecl),
144  Case.Qualifications[I]);
145  } else {
146  EXPECT_EQ(getQualification(AST.getASTContext(),
147  D->getLexicalDeclContext(), TargetDecl,
148  Case.VisibleNamespaces),
149  Case.Qualifications[I]);
150  }
151  }
152  }
153 }
154 
155 TEST(ClangdAST, PrintType) {
156  const struct {
157  llvm::StringRef Test;
158  std::vector<llvm::StringRef> Types;
159  } Cases[] = {
160  {
161  R"cpp(
162  namespace ns1 { namespace ns2 { class Foo {}; } }
163  void insert(); // ns1::ns2::Foo
164  namespace ns1 {
165  void insert(); // ns2::Foo
166  namespace ns2 {
167  void insert(); // Foo
168  }
169  }
170  )cpp",
171  {"ns1::ns2::Foo", "ns2::Foo", "Foo"},
172  },
173  {
174  R"cpp(
175  namespace ns1 {
176  typedef int Foo;
177  }
178  void insert(); // ns1::Foo
179  namespace ns1 {
180  void insert(); // Foo
181  }
182  )cpp",
183  {"ns1::Foo", "Foo"},
184  },
185  };
186  for (const auto &Case : Cases) {
187  Annotations Test(Case.Test);
188  TestTU TU = TestTU::withCode(Test.code());
189  ParsedAST AST = TU.build();
190  std::vector<const DeclContext *> InsertionPoints;
191  const TypeDecl *TargetDecl = nullptr;
192  findDecl(AST, [&](const NamedDecl &ND) {
193  if (ND.getNameAsString() == "Foo") {
194  if (const auto *TD = llvm::dyn_cast<TypeDecl>(&ND)) {
195  TargetDecl = TD;
196  return true;
197  }
198  } else if (ND.getNameAsString() == "insert")
199  InsertionPoints.push_back(ND.getDeclContext());
200  return false;
201  });
202 
203  ASSERT_EQ(InsertionPoints.size(), Case.Types.size());
204  for (size_t I = 0, E = InsertionPoints.size(); I != E; ++I) {
205  const auto *DC = InsertionPoints[I];
206  EXPECT_EQ(printType(AST.getASTContext().getTypeDeclType(TargetDecl), *DC),
207  Case.Types[I]);
208  }
209  }
210 }
211 } // namespace
212 } // namespace clangd
213 } // namespace clang
QualType DeducedType
Definition: AST.cpp:414
ParsedAST build() const
Definition: TestTU.cpp:22
const FunctionDecl * Decl
llvm::Optional< QualType > getDeducedType(ASTContext &ASTCtx, SourceLocation Loc)
Retrieves the deduced type at a given location (auto, decltype).
Definition: AST.cpp:418
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
Definition: SourceCode.cpp:571
std::string printType(const QualType QT, const DeclContext &CurContext)
Returns a QualType as string.
Definition: AST.cpp:305
TEST(BackgroundQueueTest, Priority)
std::string getQualification(ASTContext &Context, const DeclContext *DestContext, SourceLocation InsertionPoint, const NamedDecl *ND)
Gets the nested name specifier necessary for spelling ND in DestContext, at InsertionPoint.
Definition: AST.cpp:437
Position Pos
Definition: SourceCode.cpp:772
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:33
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
const Expr * E
std::string AnnotatedCode
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:118