1*9fc45ca0SDaniel Grumberg //===- ExtractAPI/TypedefUnderlyingTypeResolver.cpp -------------*- C++ -*-===//
2*9fc45ca0SDaniel Grumberg //
3*9fc45ca0SDaniel Grumberg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*9fc45ca0SDaniel Grumberg // See https://llvm.org/LICENSE.txt for license information.
5*9fc45ca0SDaniel Grumberg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*9fc45ca0SDaniel Grumberg //
7*9fc45ca0SDaniel Grumberg //===----------------------------------------------------------------------===//
8*9fc45ca0SDaniel Grumberg ///
9*9fc45ca0SDaniel Grumberg /// \file
10*9fc45ca0SDaniel Grumberg /// This file implements UnderlyingTypeResolver.
11*9fc45ca0SDaniel Grumberg ///
12*9fc45ca0SDaniel Grumberg //===----------------------------------------------------------------------===//
13*9fc45ca0SDaniel Grumberg 
14*9fc45ca0SDaniel Grumberg #include "TypedefUnderlyingTypeResolver.h"
15*9fc45ca0SDaniel Grumberg #include "clang/Index/USRGeneration.h"
16*9fc45ca0SDaniel Grumberg 
17*9fc45ca0SDaniel Grumberg using namespace clang;
18*9fc45ca0SDaniel Grumberg using namespace extractapi;
19*9fc45ca0SDaniel Grumberg 
20*9fc45ca0SDaniel Grumberg namespace {
21*9fc45ca0SDaniel Grumberg 
getUnderlyingTypeDecl(QualType Type)22*9fc45ca0SDaniel Grumberg const NamedDecl *getUnderlyingTypeDecl(QualType Type) {
23*9fc45ca0SDaniel Grumberg   const NamedDecl *TypeDecl = nullptr;
24*9fc45ca0SDaniel Grumberg 
25*9fc45ca0SDaniel Grumberg   const TypedefType *TypedefTy = Type->getAs<TypedefType>();
26*9fc45ca0SDaniel Grumberg   if (TypedefTy)
27*9fc45ca0SDaniel Grumberg     TypeDecl = TypedefTy->getDecl();
28*9fc45ca0SDaniel Grumberg   if (const TagType *TagTy = Type->getAs<TagType>()) {
29*9fc45ca0SDaniel Grumberg     TypeDecl = TagTy->getDecl();
30*9fc45ca0SDaniel Grumberg   } else if (const ObjCInterfaceType *ObjCITy =
31*9fc45ca0SDaniel Grumberg                  Type->getAs<ObjCInterfaceType>()) {
32*9fc45ca0SDaniel Grumberg     TypeDecl = ObjCITy->getDecl();
33*9fc45ca0SDaniel Grumberg   }
34*9fc45ca0SDaniel Grumberg 
35*9fc45ca0SDaniel Grumberg   if (TypeDecl && TypedefTy) {
36*9fc45ca0SDaniel Grumberg     // if this is a typedef to another typedef, use the typedef's decl for the
37*9fc45ca0SDaniel Grumberg     // USR - this will actually be in the output, unlike a typedef to an
38*9fc45ca0SDaniel Grumberg     // anonymous decl
39*9fc45ca0SDaniel Grumberg     const TypedefNameDecl *TypedefDecl = TypedefTy->getDecl();
40*9fc45ca0SDaniel Grumberg     if (TypedefDecl->getUnderlyingType()->isTypedefNameType())
41*9fc45ca0SDaniel Grumberg       TypeDecl = TypedefDecl;
42*9fc45ca0SDaniel Grumberg   }
43*9fc45ca0SDaniel Grumberg 
44*9fc45ca0SDaniel Grumberg   return TypeDecl;
45*9fc45ca0SDaniel Grumberg }
46*9fc45ca0SDaniel Grumberg 
47*9fc45ca0SDaniel Grumberg } // namespace
48*9fc45ca0SDaniel Grumberg 
49*9fc45ca0SDaniel Grumberg SymbolReference
getSymbolReferenceForType(QualType Type,APISet & API) const50*9fc45ca0SDaniel Grumberg TypedefUnderlyingTypeResolver::getSymbolReferenceForType(QualType Type,
51*9fc45ca0SDaniel Grumberg                                                          APISet &API) const {
52*9fc45ca0SDaniel Grumberg   std::string TypeName = Type.getAsString();
53*9fc45ca0SDaniel Grumberg   SmallString<128> TypeUSR;
54*9fc45ca0SDaniel Grumberg   const NamedDecl *TypeDecl = getUnderlyingTypeDecl(Type);
55*9fc45ca0SDaniel Grumberg   const TypedefType *TypedefTy = Type->getAs<TypedefType>();
56*9fc45ca0SDaniel Grumberg 
57*9fc45ca0SDaniel Grumberg   if (TypeDecl) {
58*9fc45ca0SDaniel Grumberg     if (!TypedefTy)
59*9fc45ca0SDaniel Grumberg       TypeName = TypeDecl->getName().str();
60*9fc45ca0SDaniel Grumberg 
61*9fc45ca0SDaniel Grumberg     clang::index::generateUSRForDecl(TypeDecl, TypeUSR);
62*9fc45ca0SDaniel Grumberg   } else {
63*9fc45ca0SDaniel Grumberg     clang::index::generateUSRForType(Type, Context, TypeUSR);
64*9fc45ca0SDaniel Grumberg   }
65*9fc45ca0SDaniel Grumberg 
66*9fc45ca0SDaniel Grumberg   return {API.copyString(TypeName), API.copyString(TypeUSR)};
67*9fc45ca0SDaniel Grumberg }
68*9fc45ca0SDaniel Grumberg 
getUSRForType(QualType Type) const69*9fc45ca0SDaniel Grumberg std::string TypedefUnderlyingTypeResolver::getUSRForType(QualType Type) const {
70*9fc45ca0SDaniel Grumberg   SmallString<128> TypeUSR;
71*9fc45ca0SDaniel Grumberg   const NamedDecl *TypeDecl = getUnderlyingTypeDecl(Type);
72*9fc45ca0SDaniel Grumberg 
73*9fc45ca0SDaniel Grumberg   if (TypeDecl)
74*9fc45ca0SDaniel Grumberg     clang::index::generateUSRForDecl(TypeDecl, TypeUSR);
75*9fc45ca0SDaniel Grumberg   else
76*9fc45ca0SDaniel Grumberg     clang::index::generateUSRForType(Type, Context, TypeUSR);
77*9fc45ca0SDaniel Grumberg 
78*9fc45ca0SDaniel Grumberg   return std::string(TypeUSR);
79*9fc45ca0SDaniel Grumberg }
80