1//===- CIndexUSRs.cpp - Clang-C Source Indexing Library -------------------===//
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// This file implements the generation and use of USRs from CXEntities.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIndexer.h"
14#include "CXCursor.h"
15#include "CXString.h"
16#include "CXTranslationUnit.h"
17#include "clang/Frontend/ASTUnit.h"
18#include "clang/Index/USRGeneration.h"
19#include "clang/Lex/PreprocessingRecord.h"
20#include "llvm/ADT/SmallString.h"
21#include "llvm/Support/raw_ostream.h"
22
23using namespace clang;
24using namespace clang::index;
25
26//===----------------------------------------------------------------------===//
27// API hooks.
28//===----------------------------------------------------------------------===//
29
30static inline StringRef extractUSRSuffix(StringRef s) {
31  return s.startswith("c:") ? s.substr(2) : "";
32}
33
34bool cxcursor::getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf) {
35  return generateUSRForDecl(D, Buf);
36}
37
38CXString clang_getCursorUSR(CXCursor C) {
39  const CXCursorKind &K = clang_getCursorKind(C);
40
41  if (clang_isDeclaration(K)) {
42    const Decl *D = cxcursor::getCursorDecl(C);
43    if (!D)
44      return cxstring::createEmpty();
45
46    CXTranslationUnit TU = cxcursor::getCursorTU(C);
47    if (!TU)
48      return cxstring::createEmpty();
49
50    cxstring::CXStringBuf *buf = cxstring::getCXStringBuf(TU);
51    if (!buf)
52      return cxstring::createEmpty();
53
54    bool Ignore = cxcursor::getDeclCursorUSR(D, buf->Data);
55    if (Ignore) {
56      buf->dispose();
57      return cxstring::createEmpty();
58    }
59
60    // Return the C-string, but don't make a copy since it is already in
61    // the string buffer.
62    buf->Data.push_back('\0');
63    return createCXString(buf);
64  }
65
66  if (K == CXCursor_MacroDefinition) {
67    CXTranslationUnit TU = cxcursor::getCursorTU(C);
68    if (!TU)
69      return cxstring::createEmpty();
70
71    cxstring::CXStringBuf *buf = cxstring::getCXStringBuf(TU);
72    if (!buf)
73      return cxstring::createEmpty();
74
75    bool Ignore = generateUSRForMacro(cxcursor::getCursorMacroDefinition(C),
76                                      cxtu::getASTUnit(TU)->getSourceManager(),
77                                      buf->Data);
78    if (Ignore) {
79      buf->dispose();
80      return cxstring::createEmpty();
81    }
82
83    // Return the C-string, but don't make a copy since it is already in
84    // the string buffer.
85    buf->Data.push_back('\0');
86    return createCXString(buf);
87  }
88
89  return cxstring::createEmpty();
90}
91
92CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) {
93  SmallString<128> Buf(getUSRSpacePrefix());
94  llvm::raw_svector_ostream OS(Buf);
95  OS << extractUSRSuffix(clang_getCString(classUSR));
96  generateUSRForObjCIvar(name, OS);
97  return cxstring::createDup(OS.str());
98}
99
100CXString clang_constructUSR_ObjCMethod(const char *name,
101                                       unsigned isInstanceMethod,
102                                       CXString classUSR) {
103  SmallString<128> Buf(getUSRSpacePrefix());
104  llvm::raw_svector_ostream OS(Buf);
105  OS << extractUSRSuffix(clang_getCString(classUSR));
106  generateUSRForObjCMethod(name, isInstanceMethod, OS);
107  return cxstring::createDup(OS.str());
108}
109
110CXString clang_constructUSR_ObjCClass(const char *name) {
111  SmallString<128> Buf(getUSRSpacePrefix());
112  llvm::raw_svector_ostream OS(Buf);
113  generateUSRForObjCClass(name, OS);
114  return cxstring::createDup(OS.str());
115}
116
117CXString clang_constructUSR_ObjCProtocol(const char *name) {
118  SmallString<128> Buf(getUSRSpacePrefix());
119  llvm::raw_svector_ostream OS(Buf);
120  generateUSRForObjCProtocol(name, OS);
121  return cxstring::createDup(OS.str());
122}
123
124CXString clang_constructUSR_ObjCCategory(const char *class_name,
125                                         const char *category_name) {
126  SmallString<128> Buf(getUSRSpacePrefix());
127  llvm::raw_svector_ostream OS(Buf);
128  generateUSRForObjCCategory(class_name, category_name, OS);
129  return cxstring::createDup(OS.str());
130}
131
132CXString clang_constructUSR_ObjCProperty(const char *property,
133                                         CXString classUSR) {
134  SmallString<128> Buf(getUSRSpacePrefix());
135  llvm::raw_svector_ostream OS(Buf);
136  OS << extractUSRSuffix(clang_getCString(classUSR));
137  generateUSRForObjCProperty(property, /*isClassProp=*/false, OS);
138  return cxstring::createDup(OS.str());
139}
140