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.starts_with(Prefix: "c:") ? s.substr(Start: 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(Cursor: C);
43 if (!D)
44 return cxstring::createEmpty();
45
46 CXTranslationUnit TU = cxcursor::getCursorTU(Cursor: 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&: 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(Elt: '\0');
63 return createCXString(buf);
64 }
65
66 if (K == CXCursor_MacroDefinition) {
67 CXTranslationUnit TU = cxcursor::getCursorTU(Cursor: 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(MD: cxcursor::getCursorMacroDefinition(C),
76 SM: cxtu::getASTUnit(TU)->getSourceManager(),
77 Buf&: 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(Elt: '\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(s: clang_getCString(string: classUSR));
96 generateUSRForObjCIvar(Ivar: name, OS);
97 return cxstring::createDup(String: 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(s: clang_getCString(string: classUSR));
106 generateUSRForObjCMethod(Sel: name, IsInstanceMethod: isInstanceMethod, OS);
107 return cxstring::createDup(String: 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(Cls: name, OS);
114 return cxstring::createDup(String: 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(Prot: name, OS);
121 return cxstring::createDup(String: 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(Cls: class_name, Cat: category_name, OS);
129 return cxstring::createDup(String: 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(s: clang_getCString(string: classUSR));
137 generateUSRForObjCProperty(Prop: property, /*isClassProp=*/false, OS);
138 return cxstring::createDup(String: OS.str());
139}
140