blob: f2af27cd65a7b8abec1c707106c443e58c06c9b2 [file] [log] [blame]
Ted Kremenekd2fa5662009-08-26 22:36:44 +00001//===- CIndex.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 Clang-C Source Indexing library.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang-c/Index.h"
Steve Naroff50398192009-08-28 15:28:48 +000015#include "clang/Index/Program.h"
16#include "clang/Index/Indexer.h"
Steve Naroff50398192009-08-28 15:28:48 +000017#include "clang/AST/DeclVisitor.h"
Steve Naroffc857ea42009-09-02 13:28:54 +000018#include "clang/AST/Decl.h"
Benjamin Kramerd01a0bc2009-08-29 12:56:35 +000019#include "clang/Basic/FileManager.h"
Steve Naroff2d4d6292009-08-31 14:26:51 +000020#include "clang/Basic/SourceManager.h"
Benjamin Kramerd01a0bc2009-08-29 12:56:35 +000021#include "clang/Frontend/ASTUnit.h"
22#include <cstdio>
Steve Naroff50398192009-08-28 15:28:48 +000023using namespace clang;
24using namespace idx;
25
Steve Naroff89922f82009-08-31 00:59:03 +000026namespace {
27
28// Translation Unit Visitor.
29class TUVisitor : public DeclVisitor<TUVisitor> {
30 CXTranslationUnit TUnit;
31 CXTranslationUnitIterator Callback;
Steve Naroff2b8ee6c2009-09-01 15:55:40 +000032 CXClientData CData;
33
34 void Call(enum CXCursorKind CK, NamedDecl *ND) {
35 CXCursor C = { CK, ND };
36 Callback(TUnit, C, CData);
37 }
Steve Naroff89922f82009-08-31 00:59:03 +000038public:
Steve Naroff2b8ee6c2009-09-01 15:55:40 +000039 TUVisitor(CXTranslationUnit CTU,
40 CXTranslationUnitIterator cback, CXClientData D) :
41 TUnit(CTU), Callback(cback), CData(D) {}
Steve Naroff89922f82009-08-31 00:59:03 +000042
43 void VisitTranslationUnitDecl(TranslationUnitDecl *D) {
44 VisitDeclContext(dyn_cast<DeclContext>(D));
45 }
46 void VisitDeclContext(DeclContext *DC) {
47 for (DeclContext::decl_iterator
48 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
49 Visit(*I);
50 }
Steve Naroff2b8ee6c2009-09-01 15:55:40 +000051 void VisitTypedefDecl(TypedefDecl *ND) {
52 Call(CXCursor_TypedefDecl, ND);
Steve Naroff89922f82009-08-31 00:59:03 +000053 }
54 void VisitTagDecl(TagDecl *ND) {
Steve Naroffc857ea42009-09-02 13:28:54 +000055 switch (ND->getTagKind()) {
56 case TagDecl::TK_struct:
57 Call(CXCursor_StructDecl, ND);
58 break;
59 case TagDecl::TK_class:
60 Call(CXCursor_ClassDecl, ND);
61 break;
62 case TagDecl::TK_union:
63 Call(CXCursor_UnionDecl, ND);
64 break;
65 case TagDecl::TK_enum:
66 Call(CXCursor_EnumDecl, ND);
67 break;
68 }
Steve Naroff89922f82009-08-31 00:59:03 +000069 }
70 void VisitFunctionDecl(FunctionDecl *ND) {
Steve Naroffc857ea42009-09-02 13:28:54 +000071 Call(ND->isThisDeclarationADefinition() ? CXCursor_FunctionDefn
72 : CXCursor_FunctionDecl, ND);
Steve Naroff89922f82009-08-31 00:59:03 +000073 }
74 void VisitObjCInterfaceDecl(ObjCInterfaceDecl *ND) {
Steve Naroff2b8ee6c2009-09-01 15:55:40 +000075 Call(CXCursor_ObjCInterfaceDecl, ND);
Steve Naroff89922f82009-08-31 00:59:03 +000076 }
77 void VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
Steve Naroff2b8ee6c2009-09-01 15:55:40 +000078 Call(CXCursor_ObjCCategoryDecl, ND);
Steve Naroff89922f82009-08-31 00:59:03 +000079 }
80 void VisitObjCProtocolDecl(ObjCProtocolDecl *ND) {
Steve Naroff2b8ee6c2009-09-01 15:55:40 +000081 Call(CXCursor_ObjCProtocolDecl, ND);
Steve Naroff89922f82009-08-31 00:59:03 +000082 }
Steve Naroffc857ea42009-09-02 13:28:54 +000083 void VisitObjCImplementationDecl(ObjCImplementationDecl *ND) {
84 Call(CXCursor_ObjCClassDefn, ND);
85 }
86 void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *ND) {
87 Call(CXCursor_ObjCCategoryDefn, ND);
88 }
Steve Naroff89922f82009-08-31 00:59:03 +000089};
90
Steve Naroffc857ea42009-09-02 13:28:54 +000091// Declaration visitor.
92class CDeclVisitor : public DeclVisitor<CDeclVisitor> {
93 CXDecl CDecl;
94 CXDeclIterator Callback;
95 CXClientData CData;
96
97 void Call(enum CXCursorKind CK, NamedDecl *ND) {
98 CXCursor C = { CK, ND };
99 Callback(CDecl, C, CData);
100 }
Steve Naroff89922f82009-08-31 00:59:03 +0000101public:
Steve Naroffc857ea42009-09-02 13:28:54 +0000102 CDeclVisitor(CXDecl C, CXDeclIterator cback, CXClientData D) :
103 CDecl(C), Callback(cback), CData(D) {}
104
105 void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
Steve Narofff334b4e2009-09-02 18:26:48 +0000106 // Issue callbacks for super class and protocols.
107 if (D->getSuperClass())
108 Call(CXCursor_ObjCSuperClassRef, D);
109
Steve Naroffc857ea42009-09-02 13:28:54 +0000110 VisitDeclContext(dyn_cast<DeclContext>(D));
111 }
112 void VisitTagDecl(TagDecl *D) {
113 VisitDeclContext(dyn_cast<DeclContext>(D));
114 }
115 void VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
116 VisitDeclContext(dyn_cast<DeclContext>(D));
117 }
118 void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
119 VisitDeclContext(dyn_cast<DeclContext>(D));
120 }
Steve Naroff89922f82009-08-31 00:59:03 +0000121 void VisitDeclContext(DeclContext *DC) {
122 for (DeclContext::decl_iterator
123 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
124 Visit(*I);
125 }
126 void VisitEnumConstantDecl(EnumConstantDecl *ND) {
Steve Naroffc857ea42009-09-02 13:28:54 +0000127 Call(CXCursor_EnumConstantDecl, ND);
Steve Naroff89922f82009-08-31 00:59:03 +0000128 }
129 void VisitFieldDecl(FieldDecl *ND) {
Steve Naroffc857ea42009-09-02 13:28:54 +0000130 Call(CXCursor_FieldDecl, ND);
131 }
132 void VisitObjCPropertyDecl(ObjCPropertyDecl *ND) {
133 Call(CXCursor_ObjCPropertyDecl, ND);
Steve Naroff89922f82009-08-31 00:59:03 +0000134 }
135 void VisitObjCIvarDecl(ObjCIvarDecl *ND) {
Steve Naroffc857ea42009-09-02 13:28:54 +0000136 Call(CXCursor_ObjCIvarDecl, ND);
137 }
138 void VisitObjCMethodDecl(ObjCMethodDecl *ND) {
139 if (ND->getBody()) {
140 Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDefn
141 : CXCursor_ObjCClassMethodDefn, ND);
142 // FIXME: load body.
143 } else
144 Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl
145 : CXCursor_ObjCClassMethodDecl, ND);
Steve Naroff89922f82009-08-31 00:59:03 +0000146 }
147};
148
149}
150
Steve Naroff600866c2009-08-27 19:51:58 +0000151extern "C" {
Ted Kremenekd2fa5662009-08-26 22:36:44 +0000152
Steve Naroff600866c2009-08-27 19:51:58 +0000153CXIndex clang_createIndex()
Steve Naroff50398192009-08-28 15:28:48 +0000154{
155 return new Indexer(*new Program(), *new FileManager());
Steve Naroff600866c2009-08-27 19:51:58 +0000156}
157
Steve Naroff50398192009-08-28 15:28:48 +0000158// FIXME: need to pass back error info.
159CXTranslationUnit clang_createTranslationUnit(
160 CXIndex CIdx, const char *ast_filename)
Steve Naroff600866c2009-08-27 19:51:58 +0000161{
Steve Naroff50398192009-08-28 15:28:48 +0000162 assert(CIdx && "Passed null CXIndex");
163 Indexer *CXXIdx = static_cast<Indexer *>(CIdx);
164 std::string astName(ast_filename);
165 std::string ErrMsg;
166
167 return ASTUnit::LoadFromPCHFile(astName, CXXIdx->getFileManager(), &ErrMsg);
Steve Naroff600866c2009-08-27 19:51:58 +0000168}
169
Daniel Dunbar1eb79b52009-08-28 16:30:07 +0000170
Steve Naroffc857ea42009-09-02 13:28:54 +0000171void clang_loadTranslationUnit(CXTranslationUnit CTUnit,
172 CXTranslationUnitIterator callback,
173 CXClientData CData)
Steve Naroff600866c2009-08-27 19:51:58 +0000174{
Steve Naroff50398192009-08-28 15:28:48 +0000175 assert(CTUnit && "Passed null CXTranslationUnit");
176 ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
177 ASTContext &Ctx = CXXUnit->getASTContext();
178
Steve Naroff2b8ee6c2009-09-01 15:55:40 +0000179 TUVisitor DVisit(CTUnit, callback, CData);
Steve Naroff50398192009-08-28 15:28:48 +0000180 DVisit.Visit(Ctx.getTranslationUnitDecl());
Steve Naroff600866c2009-08-27 19:51:58 +0000181}
182
Steve Naroffc857ea42009-09-02 13:28:54 +0000183void clang_loadDeclaration(CXDecl Dcl,
184 CXDeclIterator callback,
185 CXClientData CData)
Steve Naroff600866c2009-08-27 19:51:58 +0000186{
Steve Naroffc857ea42009-09-02 13:28:54 +0000187 assert(Dcl && "Passed null CXDecl");
188
189 CDeclVisitor DVisit(Dcl, callback, CData);
190 DVisit.Visit(static_cast<Decl *>(Dcl));
Steve Naroff600866c2009-08-27 19:51:58 +0000191}
192
Steve Naroff7e8f8182009-08-28 12:07:44 +0000193// Some notes on CXEntity:
194//
195// - Since the 'ordinary' namespace includes functions, data, typedefs,
196// ObjC interfaces, thecurrent algorithm is a bit naive (resulting in one
197// entity for 2 different types). For example:
198//
199// module1.m: @interface Foo @end Foo *x;
200// module2.m: void Foo(int);
201//
202// - Since the unique name spans translation units, static data/functions
203// within a CXTranslationUnit are *not* currently represented by entities.
204// As a result, there will be no entity for the following:
205//
206// module.m: static void Foo() { }
207//
208
209
Steve Naroff600866c2009-08-27 19:51:58 +0000210const char *clang_getDeclarationName(CXEntity)
211{
212 return "";
213}
214const char *clang_getURI(CXEntity)
215{
216 return "";
217}
218
219CXEntity clang_getEntity(const char *URI)
220{
221 return 0;
222}
223
224//
225// CXDecl Operations.
226//
227CXCursor clang_getCursorFromDecl(CXDecl)
228{
Steve Naroff89922f82009-08-31 00:59:03 +0000229 return CXCursor();
Steve Naroff600866c2009-08-27 19:51:58 +0000230}
231CXEntity clang_getEntityFromDecl(CXDecl)
232{
233 return 0;
234}
Steve Naroff89922f82009-08-31 00:59:03 +0000235const char *clang_getDeclSpelling(CXDecl AnonDecl)
Steve Naroff600866c2009-08-27 19:51:58 +0000236{
Steve Naroff89922f82009-08-31 00:59:03 +0000237 assert(AnonDecl && "Passed null CXDecl");
238 NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
Steve Naroffc857ea42009-09-02 13:28:54 +0000239
240 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND)) {
241 return OMD->getSelector().getAsString().c_str();
242 }
Steve Naroff89922f82009-08-31 00:59:03 +0000243 if (ND->getIdentifier())
244 return ND->getIdentifier()->getName();
Steve Naroffc857ea42009-09-02 13:28:54 +0000245 else
Steve Naroff89922f82009-08-31 00:59:03 +0000246 return "";
Steve Naroff600866c2009-08-27 19:51:58 +0000247}
Steve Narofff334b4e2009-09-02 18:26:48 +0000248
249const char *clang_getCursorSpelling(CXCursor C)
250{
251 assert(C.decl && "CXCursor has null decl");
252 NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
253
254 if (clang_isReference(C.kind)) {
255 switch (C.kind) {
256 case CXCursor_ObjCSuperClassRef:
257 ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
258 assert(OID && "clang_getCursorLine(): Missing interface decl");
259 return OID->getSuperClass()->getIdentifier()->getName();
260 default:
261 return "<not implemented>";
262 }
263 }
264 return clang_getDeclSpelling(C.decl);
265}
266
267const char *clang_getCursorKindSpelling(enum CXCursorKind Kind)
Steve Naroff600866c2009-08-27 19:51:58 +0000268{
Steve Naroff89922f82009-08-31 00:59:03 +0000269 switch (Kind) {
270 case CXCursor_FunctionDecl: return "FunctionDecl";
271 case CXCursor_TypedefDecl: return "TypedefDecl";
272 case CXCursor_EnumDecl: return "EnumDecl";
273 case CXCursor_EnumConstantDecl: return "EnumConstantDecl";
Steve Naroffc857ea42009-09-02 13:28:54 +0000274 case CXCursor_StructDecl: return "StructDecl";
275 case CXCursor_UnionDecl: return "UnionDecl";
276 case CXCursor_ClassDecl: return "ClassDecl";
Steve Naroff89922f82009-08-31 00:59:03 +0000277 case CXCursor_FieldDecl: return "FieldDecl";
278 case CXCursor_VarDecl: return "VarDecl";
279 case CXCursor_ParmDecl: return "ParmDecl";
280 case CXCursor_ObjCInterfaceDecl: return "ObjCInterfaceDecl";
281 case CXCursor_ObjCCategoryDecl: return "ObjCCategoryDecl";
282 case CXCursor_ObjCProtocolDecl: return "ObjCProtocolDecl";
283 case CXCursor_ObjCPropertyDecl: return "ObjCPropertyDecl";
284 case CXCursor_ObjCIvarDecl: return "ObjCIvarDecl";
Steve Naroffc857ea42009-09-02 13:28:54 +0000285 case CXCursor_ObjCInstanceMethodDecl: return "ObjCInstanceMethodDecl";
286 case CXCursor_ObjCClassMethodDecl: return "ObjCClassMethodDecl";
287 case CXCursor_FunctionDefn: return "FunctionDefn";
288 case CXCursor_ObjCInstanceMethodDefn: return "ObjCInstanceMethodDefn";
289 case CXCursor_ObjCClassMethodDefn: return "ObjCClassMethodDefn";
290 case CXCursor_ObjCClassDefn: return "ObjCClassDefn";
291 case CXCursor_ObjCCategoryDefn: return "ObjCCategoryDefn";
Steve Narofff334b4e2009-09-02 18:26:48 +0000292 case CXCursor_ObjCSuperClassRef: return "ObjCSuperClassRef";
Steve Naroff89922f82009-08-31 00:59:03 +0000293 default: return "<not implemented>";
294 }
Steve Naroff600866c2009-08-27 19:51:58 +0000295}
Steve Naroff89922f82009-08-31 00:59:03 +0000296
Steve Naroff600866c2009-08-27 19:51:58 +0000297//
298// CXCursor Operations.
299//
300CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
301 unsigned line, unsigned column)
302{
Steve Naroff89922f82009-08-31 00:59:03 +0000303 return CXCursor();
Steve Naroff600866c2009-08-27 19:51:58 +0000304}
305
306CXCursorKind clang_getCursorKind(CXCursor)
307{
Steve Naroff89922f82009-08-31 00:59:03 +0000308 return CXCursor_Invalid;
Steve Naroff600866c2009-08-27 19:51:58 +0000309}
310
Steve Naroff89922f82009-08-31 00:59:03 +0000311unsigned clang_isDeclaration(enum CXCursorKind K)
312{
313 return K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl;
314}
Steve Naroff2d4d6292009-08-31 14:26:51 +0000315
Steve Narofff334b4e2009-09-02 18:26:48 +0000316unsigned clang_isReference(enum CXCursorKind K)
317{
318 return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
319}
320
321unsigned clang_isDefinition(enum CXCursorKind K)
322{
323 return K >= CXCursor_FirstDefn && K <= CXCursor_LastDefn;
324}
325
326static SourceLocation getLocationFromCursor(CXCursor C,
327 SourceManager &SourceMgr,
328 NamedDecl *ND) {
329 SourceLocation SLoc;
330 if (clang_isReference(C.kind)) {
331 switch (C.kind) {
332 case CXCursor_ObjCSuperClassRef:
333 ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
334 assert(OID && "clang_getCursorLine(): Missing interface decl");
335 SLoc = OID->getSuperClassLoc();
336 break;
337 default:
338 break;
339 }
340 } else { // We have a declaration or a definition.
341 SLoc = ND->getLocation();
342 if (SLoc.isInvalid())
343 return SourceLocation();
344 SLoc = SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
345 }
346 return SLoc;
347}
348
Steve Naroff2d4d6292009-08-31 14:26:51 +0000349unsigned clang_getCursorLine(CXCursor C)
Steve Naroff600866c2009-08-27 19:51:58 +0000350{
Steve Naroff2d4d6292009-08-31 14:26:51 +0000351 assert(C.decl && "CXCursor has null decl");
352 NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000353 SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
Steve Narofff334b4e2009-09-02 18:26:48 +0000354
355 SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000356 return SourceMgr.getSpellingLineNumber(SLoc);
Steve Naroff600866c2009-08-27 19:51:58 +0000357}
Steve Narofff334b4e2009-09-02 18:26:48 +0000358
Steve Naroff2d4d6292009-08-31 14:26:51 +0000359unsigned clang_getCursorColumn(CXCursor C)
Steve Naroff600866c2009-08-27 19:51:58 +0000360{
Steve Naroff2d4d6292009-08-31 14:26:51 +0000361 assert(C.decl && "CXCursor has null decl");
362 NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000363 SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
Steve Narofff334b4e2009-09-02 18:26:48 +0000364
365 SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000366 return SourceMgr.getSpellingColumnNumber(SLoc);
Steve Naroff600866c2009-08-27 19:51:58 +0000367}
Steve Naroff2d4d6292009-08-31 14:26:51 +0000368const char *clang_getCursorSource(CXCursor C)
Steve Naroff600866c2009-08-27 19:51:58 +0000369{
Steve Naroff2d4d6292009-08-31 14:26:51 +0000370 assert(C.decl && "CXCursor has null decl");
371 NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000372 SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
Steve Narofff334b4e2009-09-02 18:26:48 +0000373
374 SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000375 return SourceMgr.getBufferName(SLoc);
Steve Naroff600866c2009-08-27 19:51:58 +0000376}
377
378// If CXCursorKind == Cursor_Reference, then this will return the referenced declaration.
379// If CXCursorKind == Cursor_Declaration, then this will return the declaration.
380CXDecl clang_getCursorDecl(CXCursor)
381{
382 return 0;
383}
384
385} // end extern "C"