clang-tools  11.0.0
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  SourceManagerForFile SM("foo.cpp", File.code());
41 
42  for (Position Pos : File.points()) {
43  auto Location = sourceLocationInMainFile(SM.get(), Pos);
44  ASSERT_TRUE(!!Location) << llvm::toString(Location.takeError());
46  EXPECT_EQ(DeducedType->getAsString(), T.DeducedType);
47  }
48  }
49 }
50 
51 TEST(ClangdAST, GetQualification) {
52  // Tries to insert the decl `Foo` into position of each decl named `insert`.
53  // This is done to get an appropriate DeclContext for the insertion location.
54  // Qualifications are the required nested name specifier to spell `Foo` at the
55  // `insert`ion location.
56  // VisibleNamespaces are assumed to be visible at every insertion location.
57  const struct {
58  llvm::StringRef Test;
59  std::vector<llvm::StringRef> Qualifications;
60  std::vector<std::string> VisibleNamespaces;
61  } Cases[] = {
62  {
63  R"cpp(
64  namespace ns1 { namespace ns2 { class Foo {}; } }
65  void insert(); // ns1::ns2::Foo
66  namespace ns1 {
67  void insert(); // ns2::Foo
68  namespace ns2 {
69  void insert(); // Foo
70  }
71  using namespace ns2;
72  void insert(); // Foo
73  }
74  using namespace ns1;
75  void insert(); // ns2::Foo
76  using namespace ns2;
77  void insert(); // Foo
78  )cpp",
79  {"ns1::ns2::", "ns2::", "", "", "ns2::", ""},
80  {},
81  },
82  {
83  R"cpp(
84  namespace ns1 { namespace ns2 { class Bar { void Foo(); }; } }
85  void insert(); // ns1::ns2::Bar::Foo
86  namespace ns1 {
87  void insert(); // ns2::Bar::Foo
88  namespace ns2 {
89  void insert(); // Bar::Foo
90  }
91  using namespace ns2;
92  void insert(); // Bar::Foo
93  }
94  using namespace ns1;
95  void insert(); // ns2::Bar::Foo
96  using namespace ns2;
97  void insert(); // Bar::Foo
98  )cpp",
99  {"ns1::ns2::Bar::", "ns2::Bar::", "Bar::", "Bar::", "ns2::Bar::",
100  "Bar::"},
101  {},
102  },
103  {
104  R"cpp(
105  namespace ns1 { namespace ns2 { void Foo(); } }
106  void insert(); // ns2::Foo
107  namespace ns1 {
108  void insert(); // ns2::Foo
109  namespace ns2 {
110  void insert(); // Foo
111  }
112  }
113  )cpp",
114  {"ns2::", "ns2::", ""},
115  {"ns1::"},
116  },
117  };
118  for (const auto &Case : Cases) {
119  Annotations Test(Case.Test);
120  TestTU TU = TestTU::withCode(Test.code());
121  ParsedAST AST = TU.build();
122  std::vector<const Decl *> InsertionPoints;
123  const NamedDecl *TargetDecl;
124  findDecl(AST, [&](const NamedDecl &ND) {
125  if (ND.getNameAsString() == "Foo") {
126  TargetDecl = &ND;
127  return true;
128  }
129 
130  if (ND.getNameAsString() == "insert")
131  InsertionPoints.push_back(&ND);
132  return false;
133  });
134 
135  ASSERT_EQ(InsertionPoints.size(), Case.Qualifications.size());
136  for (size_t I = 0, E = InsertionPoints.size(); I != E; ++I) {
137  const Decl *D = InsertionPoints[I];
138  if (Case.VisibleNamespaces.empty()) {
139  EXPECT_EQ(getQualification(AST.getASTContext(),
140  D->getLexicalDeclContext(), D->getBeginLoc(),
141  TargetDecl),
142  Case.Qualifications[I]);
143  } else {
144  EXPECT_EQ(getQualification(AST.getASTContext(),
145  D->getLexicalDeclContext(), TargetDecl,
146  Case.VisibleNamespaces),
147  Case.Qualifications[I]);
148  }
149  }
150  }
151 }
152 
153 TEST(ClangdAST, PrintType) {
154  const struct {
155  llvm::StringRef Test;
156  std::vector<llvm::StringRef> Types;
157  } Cases[] = {
158  {
159  R"cpp(
160  namespace ns1 { namespace ns2 { class Foo {}; } }
161  void insert(); // ns1::ns2::Foo
162  namespace ns1 {
163  void insert(); // ns2::Foo
164  namespace ns2 {
165  void insert(); // Foo
166  }
167  }
168  )cpp",
169  {"ns1::ns2::Foo", "ns2::Foo", "Foo"},
170  },
171  {
172  R"cpp(
173  namespace ns1 {
174  typedef int Foo;
175  }
176  void insert(); // ns1::Foo
177  namespace ns1 {
178  void insert(); // Foo
179  }
180  )cpp",
181  {"ns1::Foo", "Foo"},
182  },
183  };
184  for (const auto &Case : Cases) {
185  Annotations Test(Case.Test);
186  TestTU TU = TestTU::withCode(Test.code());
187  ParsedAST AST = TU.build();
188  std::vector<const DeclContext *> InsertionPoints;
189  const TypeDecl *TargetDecl = nullptr;
190  findDecl(AST, [&](const NamedDecl &ND) {
191  if (ND.getNameAsString() == "Foo") {
192  if (const auto *TD = llvm::dyn_cast<TypeDecl>(&ND)) {
193  TargetDecl = TD;
194  return true;
195  }
196  } else if (ND.getNameAsString() == "insert")
197  InsertionPoints.push_back(ND.getDeclContext());
198  return false;
199  });
200 
201  ASSERT_EQ(InsertionPoints.size(), Case.Types.size());
202  for (size_t I = 0, E = InsertionPoints.size(); I != E; ++I) {
203  const auto *DC = InsertionPoints[I];
204  EXPECT_EQ(printType(AST.getASTContext().getTypeDeclType(TargetDecl), *DC),
205  Case.Types[I]);
206  }
207  }
208 }
209 } // namespace
210 } // namespace clangd
211 } // namespace clang
clang::clangd::findDecl
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:165
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:704
E
const Expr * E
Definition: AvoidBindCheck.cpp:88
clang::clangd::ParsedAST::getASTContext
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
Definition: ParsedAST.cpp:471
Location
Definition: Modularize.cpp:383
TestTU.h
clang::clangd::getDeducedType
llvm::Optional< QualType > getDeducedType(ASTContext &ASTCtx, SourceLocation Loc)
Retrieves the deduced type at a given location (auto, decltype).
Definition: AST.cpp:417
clang::clangd::ParsedAST::build
static llvm::Optional< ParsedAST > build(llvm::StringRef Filename, const ParseInputs &Inputs, std::unique_ptr< clang::CompilerInvocation > CI, llvm::ArrayRef< Diag > CompilerInvocationDiags, std::shared_ptr< const PreambleData > Preamble)
Attempts to run Clang and store the parsed AST.
Definition: ParsedAST.cpp:246
AnnotatedCode
std::string AnnotatedCode
Definition: FindTargetTests.cpp:631
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:100
clang::clangd::TestTU::withCode
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:35
Annotations.h
clang::clangd::getQualification
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:428
DeducedType
QualType DeducedType
Definition: AST.cpp:413
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::tidy::cppcoreguidelines::toString
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
Definition: SpecialMemberFunctionsCheck.cpp:60
Pos
Position Pos
Definition: SourceCode.cpp:649
clang::clangd::printType
std::string printType(const QualType QT, const DeclContext &CurContext)
Returns a QualType as string.
Definition: AST.cpp:304
clang::clangd::sourceLocationInMainFile
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
Definition: SourceCode.cpp:461
AST.h
ParsedAST.h