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 
23 using namespace clang;
24 using namespace clang::index;
25 
26 //===----------------------------------------------------------------------===//
27 // API hooks.
28 //===----------------------------------------------------------------------===//
29 
extractUSRSuffix(StringRef s)30 static inline StringRef extractUSRSuffix(StringRef s) {
31   return s.startswith("c:") ? s.substr(2) : "";
32 }
33 
getDeclCursorUSR(const Decl * D,SmallVectorImpl<char> & Buf)34 bool cxcursor::getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf) {
35   return generateUSRForDecl(D, Buf);
36 }
37 
clang_getCursorUSR(CXCursor C)38 CXString 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 
clang_constructUSR_ObjCIvar(const char * name,CXString classUSR)92 CXString 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 
clang_constructUSR_ObjCMethod(const char * name,unsigned isInstanceMethod,CXString classUSR)100 CXString 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 
clang_constructUSR_ObjCClass(const char * name)110 CXString 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 
clang_constructUSR_ObjCProtocol(const char * name)117 CXString 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 
clang_constructUSR_ObjCCategory(const char * class_name,const char * category_name)124 CXString 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 
clang_constructUSR_ObjCProperty(const char * property,CXString classUSR)132 CXString 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