1 //===- ExtractAPI/TypedefUnderlyingTypeResolver.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 /// \file
10 /// This file implements UnderlyingTypeResolver.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "TypedefUnderlyingTypeResolver.h"
15 #include "clang/Index/USRGeneration.h"
16 
17 using namespace clang;
18 using namespace extractapi;
19 
20 const NamedDecl *
21 TypedefUnderlyingTypeResolver::getUnderlyingTypeDecl(QualType Type) const {
22   const NamedDecl *TypeDecl = nullptr;
23 
24   const TypedefType *TypedefTy = Type->getAs<TypedefType>();
25   if (TypedefTy)
26     TypeDecl = TypedefTy->getDecl();
27   if (const TagType *TagTy = Type->getAs<TagType>()) {
28     TypeDecl = TagTy->getDecl();
29   } else if (const ObjCInterfaceType *ObjCITy =
30                  Type->getAs<ObjCInterfaceType>()) {
31     TypeDecl = ObjCITy->getDecl();
32   }
33 
34   if (TypeDecl && TypedefTy) {
35     // if this is a typedef to another typedef, use the typedef's decl for the
36     // USR - this will actually be in the output, unlike a typedef to an
37     // anonymous decl
38     const TypedefNameDecl *TypedefDecl = TypedefTy->getDecl();
39     if (TypedefDecl->getUnderlyingType()->isTypedefNameType())
40       TypeDecl = TypedefDecl;
41   }
42 
43   return TypeDecl;
44 }
45 
46 SymbolReference
47 TypedefUnderlyingTypeResolver::getSymbolReferenceForType(QualType Type,
48                                                          APISet &API) const {
49   std::string TypeName = Type.getAsString();
50   SmallString<128> TypeUSR;
51   const NamedDecl *TypeDecl = getUnderlyingTypeDecl(Type);
52   const TypedefType *TypedefTy = Type->getAs<TypedefType>();
53 
54   if (TypeDecl) {
55     if (!TypedefTy)
56       TypeName = TypeDecl->getName().str();
57 
58     clang::index::generateUSRForDecl(TypeDecl, TypeUSR);
59   } else {
60     clang::index::generateUSRForType(Type, Context, TypeUSR);
61   }
62 
63   return {API.copyString(TypeName), API.copyString(TypeUSR)};
64 }
65 
66 std::string TypedefUnderlyingTypeResolver::getUSRForType(QualType Type) const {
67   SmallString<128> TypeUSR;
68   const NamedDecl *TypeDecl = getUnderlyingTypeDecl(Type);
69 
70   if (TypeDecl)
71     clang::index::generateUSRForDecl(TypeDecl, TypeUSR);
72   else
73     clang::index::generateUSRForType(Type, Context, TypeUSR);
74 
75   return std::string(TypeUSR);
76 }
77