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