1 //===-- ExpectedTypeTest.cpp -----------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "ExpectedTypes.h"
10 #include "ParsedAST.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"
23 using ::testing::Field
;
24 using ::testing::Matcher
;
25 using ::testing::SizeIs
;
26 using ::testing::UnorderedElementsAreArray
;
28 class ExpectedTypeConversionTest
: public ::testing::Test
{
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
));
74 ASTContext
&astCtx() { return AST
->getASTContext(); }
77 // Set after calling build().
78 llvm::Optional
<ParsedAST
> AST
;
81 TEST_F(ExpectedTypeConversionTest
, BasicTypes
) {
97 // user-defined types.
102 EXPECT_THAT(buildEquivClasses({"b", "i", "ui", "ll", "f", "d", "iptr", "bptr",
112 TEST_F(ExpectedTypeConversionTest
, ReferencesDontMatter
) {
116 const int & const_ref = noref;
120 EXPECT_THAT(buildEquivClasses({"noref", "ref", "const_ref", "rv_ref"}),
124 TEST_F(ExpectedTypeConversionTest
, ArraysDecay
) {
127 int (&arr_ref)[2] = arr;
131 EXPECT_THAT(buildEquivClasses({"arr", "arr_ref", "ptr"}), SizeIs(1));
134 TEST_F(ExpectedTypeConversionTest
, FunctionReturns
) {
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
) {
153 int* returns_not_dependent();
155 T* returns_dependent();
158 int* var_not_dependent = nullptr;
160 T* var_dependent = nullptr;
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
);
174 } // namespace clangd