brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.7 KiB · afefa24 Raw
176 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 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/StringRef.h"15#include "gmock/gmock.h"16#include "gtest/gtest.h"17#include <optional>18 19namespace clang {20namespace clangd {21namespace {22 23using ::testing::Field;24using ::testing::Matcher;25using ::testing::SizeIs;26using ::testing::UnorderedElementsAreArray;27 28class ExpectedTypeConversionTest : public ::testing::Test {29protected:30  void build(llvm::StringRef Code) {31    assert(!AST && "AST built twice");32    AST = TestTU::withCode(Code).build();33  }34 35  const NamedDecl *decl(llvm::StringRef Name) { return &findDecl(*AST, Name); }36 37  QualType typeOf(llvm::StringRef Name) {38    return cast<ValueDecl>(decl(Name))->getType().getCanonicalType();39  }40 41  /// An overload for convenience.42  std::optional<OpaqueType> fromCompletionResult(const NamedDecl *D) {43    return OpaqueType::fromCompletionResult(44        astCtx(), CodeCompletionResult(D, CCP_Declaration));45  }46 47  /// A set of DeclNames whose type match each other computed by48  /// OpaqueType::fromCompletionResult.49  using EquivClass = std::set<std::string>;50 51  Matcher<std::map<std::string, EquivClass>>52  classesAre(llvm::ArrayRef<EquivClass> Classes) {53    using MapEntry = std::map<std::string, EquivClass>::value_type;54 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);60  }61 62  // Groups \p Decls into equivalence classes based on the result of63  // '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));70    }71    return Classes;72  }73 74  ASTContext &astCtx() { return AST->getASTContext(); }75 76private:77  // Set after calling build().78  std::optional<ParsedAST> AST;79};80 81TEST_F(ExpectedTypeConversionTest, BasicTypes) {82  build(R"cpp(83    // ints.84    bool b;85    int i;86    unsigned int ui;87    long long ll;88 89    // floats.90    float f;91    double d;92 93    // pointers94    int* iptr;95    bool* bptr;96 97    // user-defined types.98    struct X {};99    X user_type;100  )cpp");101 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"}}));110}111 112TEST_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");119 120  EXPECT_THAT(buildEquivClasses({"noref", "ref", "const_ref", "rv_ref"}),121              SizeIs(1));122}123 124TEST_F(ExpectedTypeConversionTest, ArraysDecay) {125  build(R"cpp(126     int arr[2];127     int (&arr_ref)[2] = arr;128     int *ptr;129  )cpp");130 131  EXPECT_THAT(buildEquivClasses({"arr", "arr_ref", "ptr"}), SizeIs(1));132}133 134TEST_F(ExpectedTypeConversionTest, FunctionReturns) {135  build(R"cpp(136     int returns_int();137     int* returns_ptr();138 139     int int_;140     int* int_ptr;141  )cpp");142 143  OpaqueType IntTy = *OpaqueType::fromType(astCtx(), typeOf("int_"));144  EXPECT_EQ(fromCompletionResult(decl("returns_int")), IntTy);145 146  OpaqueType IntPtrTy = *OpaqueType::fromType(astCtx(), typeOf("int_ptr"));147  EXPECT_EQ(fromCompletionResult(decl("returns_ptr")), IntPtrTy);148}149 150TEST_F(ExpectedTypeConversionTest, Templates) {151  build(R"cpp(152template <class T>153int* returns_not_dependent();154template <class T>155T* returns_dependent();156 157template <class T>158int* var_not_dependent = nullptr;159template <class T>160T* var_dependent = nullptr;161 162int* int_ptr_;163  )cpp");164 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")), std::nullopt);168 169  EXPECT_EQ(fromCompletionResult(decl("var_not_dependent")), IntPtrTy);170  EXPECT_EQ(fromCompletionResult(decl("var_dependent")), std::nullopt);171}172 173} // namespace174} // namespace clangd175} // namespace clang176