clang-tools 10.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 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
DeducedType
QualType DeducedType
Definition: AST.cpp:414
clang::clangd::TestTU::build
ParsedAST build() const
Definition: TestTU.cpp:22
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:93
AST.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:418
clang::tidy::cppcoreguidelines::toString
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
Definition: SpecialMemberFunctionsCheck.cpp:58
TestTU.h
clang::clangd::sourceLocationInMainFile
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
Definition: SourceCode.cpp:571
clang::clangd::printType
std::string printType(const QualType QT, const DeclContext &CurContext)
Returns a QualType as string.
Definition: AST.cpp:305
clang::clangd::SymbolOrigin::AST
Annotations.h
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:647
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:437
Pos
Position Pos
Definition: SourceCode.cpp:772
clang::clangd::TestTU::withCode
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:33
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
ParsedAST.h
E
const Expr * E
Definition: AvoidBindCheck.cpp:82
AnnotatedCode
std::string AnnotatedCode
Definition: FindTargetTests.cpp:552
clang::clangd::CompletionItemKind::File
clang::clangd::findDecl
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:118
Location
Definition: Modularize.cpp:383