[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang-tools-extra / clangd / unittests / ExpectedTypeTest.cpp
blob88c37005eaec70ec0b7c45b72df29a6481c62bb6
1 //===-- ExpectedTypeTest.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 //===----------------------------------------------------------------------===//
9 #include "ExpectedTypes.h"
10 #include "ParsedAST.h"
11 #include "TestTU.h"
12 #include "clang/AST/ASTContext.h"
13 #include "clang/AST/Decl.h"
14 #include "llvm/ADT/None.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "gmock/gmock.h"
17 #include "gtest/gtest.h"
19 namespace clang {
20 namespace clangd {
21 namespace {
23 using ::testing::Field;
24 using ::testing::Matcher;
25 using ::testing::SizeIs;
26 using ::testing::UnorderedElementsAreArray;
28 class ExpectedTypeConversionTest : public ::testing::Test {
29 protected:
30 void build(llvm::StringRef Code) {
31 assert(!AST && "AST built twice");
32 AST = TestTU::withCode(Code).build();
35 const NamedDecl *decl(llvm::StringRef Name) { return &findDecl(*AST, Name); }
37 QualType typeOf(llvm::StringRef Name) {
38 return cast<ValueDecl>(decl(Name))->getType().getCanonicalType();
41 /// An overload for convenience.
42 llvm::Optional<OpaqueType> fromCompletionResult(const NamedDecl *D) {
43 return OpaqueType::fromCompletionResult(
44 astCtx(), CodeCompletionResult(D, CCP_Declaration));
47 /// A set of DeclNames whose type match each other computed by
48 /// OpaqueType::fromCompletionResult.
49 using EquivClass = std::set<std::string>;
51 Matcher<std::map<std::string, EquivClass>>
52 classesAre(llvm::ArrayRef<EquivClass> Classes) {
53 using MapEntry = std::map<std::string, EquivClass>::value_type;
55 std::vector<Matcher<MapEntry>> Elements;
56 Elements.reserve(Classes.size());
57 for (auto &Cls : Classes)
58 Elements.push_back(Field(&MapEntry::second, Cls));
59 return UnorderedElementsAreArray(Elements);
62 // Groups \p Decls into equivalence classes based on the result of
63 // 'OpaqueType::fromCompletionResult'.
64 std::map<std::string, EquivClass>
65 buildEquivClasses(llvm::ArrayRef<llvm::StringRef> DeclNames) {
66 std::map<std::string, EquivClass> Classes;
67 for (llvm::StringRef Name : DeclNames) {
68 auto Type = OpaqueType::fromType(astCtx(), typeOf(Name));
69 Classes[std::string(Type->raw())].insert(std::string(Name));
71 return Classes;
74 ASTContext &astCtx() { return AST->getASTContext(); }
76 private:
77 // Set after calling build().
78 llvm::Optional<ParsedAST> AST;
81 TEST_F(ExpectedTypeConversionTest, BasicTypes) {
82 build(R"cpp(
83 // ints.
84 bool b;
85 int i;
86 unsigned int ui;
87 long long ll;
89 // floats.
90 float f;
91 double d;
93 // pointers
94 int* iptr;
95 bool* bptr;
97 // user-defined types.
98 struct X {};
99 X user_type;
100 )cpp");
102 EXPECT_THAT(buildEquivClasses({"b", "i", "ui", "ll", "f", "d", "iptr", "bptr",
103 "user_type"}),
104 classesAre({{"b"},
105 {"i", "ui", "ll"},
106 {"f", "d"},
107 {"iptr"},
108 {"bptr"},
109 {"user_type"}}));
112 TEST_F(ExpectedTypeConversionTest, ReferencesDontMatter) {
113 build(R"cpp(
114 int noref;
115 int & ref = noref;
116 const int & const_ref = noref;
117 int && rv_ref = 10;
118 )cpp");
120 EXPECT_THAT(buildEquivClasses({"noref", "ref", "const_ref", "rv_ref"}),
121 SizeIs(1));
124 TEST_F(ExpectedTypeConversionTest, ArraysDecay) {
125 build(R"cpp(
126 int arr[2];
127 int (&arr_ref)[2] = arr;
128 int *ptr;
129 )cpp");
131 EXPECT_THAT(buildEquivClasses({"arr", "arr_ref", "ptr"}), SizeIs(1));
134 TEST_F(ExpectedTypeConversionTest, FunctionReturns) {
135 build(R"cpp(
136 int returns_int();
137 int* returns_ptr();
139 int int_;
140 int* int_ptr;
141 )cpp");
143 OpaqueType IntTy = *OpaqueType::fromType(astCtx(), typeOf("int_"));
144 EXPECT_EQ(fromCompletionResult(decl("returns_int")), IntTy);
146 OpaqueType IntPtrTy = *OpaqueType::fromType(astCtx(), typeOf("int_ptr"));
147 EXPECT_EQ(fromCompletionResult(decl("returns_ptr")), IntPtrTy);
150 TEST_F(ExpectedTypeConversionTest, Templates) {
151 build(R"cpp(
152 template <class T>
153 int* returns_not_dependent();
154 template <class T>
155 T* returns_dependent();
157 template <class T>
158 int* var_not_dependent = nullptr;
159 template <class T>
160 T* var_dependent = nullptr;
162 int* int_ptr_;
163 )cpp");
165 auto IntPtrTy = *OpaqueType::fromType(astCtx(), typeOf("int_ptr_"));
166 EXPECT_EQ(fromCompletionResult(decl("returns_not_dependent")), IntPtrTy);
167 EXPECT_EQ(fromCompletionResult(decl("returns_dependent")), llvm::None);
169 EXPECT_EQ(fromCompletionResult(decl("var_not_dependent")), IntPtrTy);
170 EXPECT_EQ(fromCompletionResult(decl("var_dependent")), llvm::None);
173 } // namespace
174 } // namespace clangd
175 } // namespace clang