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