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 "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
15#include "clang/Index/USRGeneration.h"
16
17using namespace clang;
18using namespace extractapi;
19
20const NamedDecl *
21TypedefUnderlyingTypeResolver::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
46SymbolReference
47TypedefUnderlyingTypeResolver::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
66std::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