blob: 82f7fb8e2b61df3eb85f9823e8eb60608d137118 [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) {
Steve Naroff1164d852009-09-02 18:58:52 +0000256 case CXCursor_ObjCSuperClassRef:
257 {
Steve Narofff334b4e2009-09-02 18:26:48 +0000258 ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
259 assert(OID && "clang_getCursorLine(): Missing interface decl");
260 return OID->getSuperClass()->getIdentifier()->getName();
Steve Naroff1164d852009-09-02 18:58:52 +0000261 }
Steve Narofff334b4e2009-09-02 18:26:48 +0000262 default:
263 return "<not implemented>";
264 }
265 }
266 return clang_getDeclSpelling(C.decl);
267}
268
269const char *clang_getCursorKindSpelling(enum CXCursorKind Kind)
Steve Naroff600866c2009-08-27 19:51:58 +0000270{
Steve Naroff89922f82009-08-31 00:59:03 +0000271 switch (Kind) {
272 case CXCursor_FunctionDecl: return "FunctionDecl";
273 case CXCursor_TypedefDecl: return "TypedefDecl";
274 case CXCursor_EnumDecl: return "EnumDecl";
275 case CXCursor_EnumConstantDecl: return "EnumConstantDecl";
Steve Naroffc857ea42009-09-02 13:28:54 +0000276 case CXCursor_StructDecl: return "StructDecl";
277 case CXCursor_UnionDecl: return "UnionDecl";
278 case CXCursor_ClassDecl: return "ClassDecl";
Steve Naroff89922f82009-08-31 00:59:03 +0000279 case CXCursor_FieldDecl: return "FieldDecl";
280 case CXCursor_VarDecl: return "VarDecl";
281 case CXCursor_ParmDecl: return "ParmDecl";
282 case CXCursor_ObjCInterfaceDecl: return "ObjCInterfaceDecl";
283 case CXCursor_ObjCCategoryDecl: return "ObjCCategoryDecl";
284 case CXCursor_ObjCProtocolDecl: return "ObjCProtocolDecl";
285 case CXCursor_ObjCPropertyDecl: return "ObjCPropertyDecl";
286 case CXCursor_ObjCIvarDecl: return "ObjCIvarDecl";
Steve Naroffc857ea42009-09-02 13:28:54 +0000287 case CXCursor_ObjCInstanceMethodDecl: return "ObjCInstanceMethodDecl";
288 case CXCursor_ObjCClassMethodDecl: return "ObjCClassMethodDecl";
289 case CXCursor_FunctionDefn: return "FunctionDefn";
290 case CXCursor_ObjCInstanceMethodDefn: return "ObjCInstanceMethodDefn";
291 case CXCursor_ObjCClassMethodDefn: return "ObjCClassMethodDefn";
292 case CXCursor_ObjCClassDefn: return "ObjCClassDefn";
293 case CXCursor_ObjCCategoryDefn: return "ObjCCategoryDefn";
Steve Narofff334b4e2009-09-02 18:26:48 +0000294 case CXCursor_ObjCSuperClassRef: return "ObjCSuperClassRef";
Steve Naroff89922f82009-08-31 00:59:03 +0000295 default: return "<not implemented>";
296 }
Steve Naroff600866c2009-08-27 19:51:58 +0000297}
Steve Naroff89922f82009-08-31 00:59:03 +0000298
Steve Naroff600866c2009-08-27 19:51:58 +0000299//
300// CXCursor Operations.
301//
302CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
303 unsigned line, unsigned column)
304{
Steve Naroff89922f82009-08-31 00:59:03 +0000305 return CXCursor();
Steve Naroff600866c2009-08-27 19:51:58 +0000306}
307
308CXCursorKind clang_getCursorKind(CXCursor)
309{
Steve Naroff89922f82009-08-31 00:59:03 +0000310 return CXCursor_Invalid;
Steve Naroff600866c2009-08-27 19:51:58 +0000311}
312
Steve Naroff89922f82009-08-31 00:59:03 +0000313unsigned clang_isDeclaration(enum CXCursorKind K)
314{
315 return K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl;
316}
Steve Naroff2d4d6292009-08-31 14:26:51 +0000317
Steve Narofff334b4e2009-09-02 18:26:48 +0000318unsigned clang_isReference(enum CXCursorKind K)
319{
320 return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
321}
322
323unsigned clang_isDefinition(enum CXCursorKind K)
324{
325 return K >= CXCursor_FirstDefn && K <= CXCursor_LastDefn;
326}
327
328static SourceLocation getLocationFromCursor(CXCursor C,
329 SourceManager &SourceMgr,
330 NamedDecl *ND) {
Steve Narofff334b4e2009-09-02 18:26:48 +0000331 if (clang_isReference(C.kind)) {
332 switch (C.kind) {
333 case CXCursor_ObjCSuperClassRef:
Steve Naroff1164d852009-09-02 18:58:52 +0000334 {
Steve Narofff334b4e2009-09-02 18:26:48 +0000335 ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
336 assert(OID && "clang_getCursorLine(): Missing interface decl");
Steve Naroff1164d852009-09-02 18:58:52 +0000337 return OID->getSuperClassLoc();
338 }
Steve Narofff334b4e2009-09-02 18:26:48 +0000339 default:
Steve Naroff1164d852009-09-02 18:58:52 +0000340 return SourceLocation();
Steve Narofff334b4e2009-09-02 18:26:48 +0000341 }
342 } else { // We have a declaration or a definition.
Steve Naroff1164d852009-09-02 18:58:52 +0000343 SourceLocation SLoc = ND->getLocation();
Steve Narofff334b4e2009-09-02 18:26:48 +0000344 if (SLoc.isInvalid())
345 return SourceLocation();
Steve Naroff1164d852009-09-02 18:58:52 +0000346 return SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
Steve Narofff334b4e2009-09-02 18:26:48 +0000347 }
Steve Narofff334b4e2009-09-02 18:26:48 +0000348}
349
Steve Naroff2d4d6292009-08-31 14:26:51 +0000350unsigned clang_getCursorLine(CXCursor C)
Steve Naroff600866c2009-08-27 19:51:58 +0000351{
Steve Naroff2d4d6292009-08-31 14:26:51 +0000352 assert(C.decl && "CXCursor has null decl");
353 NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000354 SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
Steve Narofff334b4e2009-09-02 18:26:48 +0000355
356 SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000357 return SourceMgr.getSpellingLineNumber(SLoc);
Steve Naroff600866c2009-08-27 19:51:58 +0000358}
Steve Narofff334b4e2009-09-02 18:26:48 +0000359
Steve Naroff2d4d6292009-08-31 14:26:51 +0000360unsigned clang_getCursorColumn(CXCursor C)
Steve Naroff600866c2009-08-27 19:51:58 +0000361{
Steve Naroff2d4d6292009-08-31 14:26:51 +0000362 assert(C.decl && "CXCursor has null decl");
363 NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000364 SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
Steve Narofff334b4e2009-09-02 18:26:48 +0000365
366 SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000367 return SourceMgr.getSpellingColumnNumber(SLoc);
Steve Naroff600866c2009-08-27 19:51:58 +0000368}
Steve Naroff2d4d6292009-08-31 14:26:51 +0000369const char *clang_getCursorSource(CXCursor C)
Steve Naroff600866c2009-08-27 19:51:58 +0000370{
Steve Naroff2d4d6292009-08-31 14:26:51 +0000371 assert(C.decl && "CXCursor has null decl");
372 NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000373 SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
Steve Narofff334b4e2009-09-02 18:26:48 +0000374
375 SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
Steve Naroff2d4d6292009-08-31 14:26:51 +0000376 return SourceMgr.getBufferName(SLoc);
Steve Naroff600866c2009-08-27 19:51:58 +0000377}
378
379// If CXCursorKind == Cursor_Reference, then this will return the referenced declaration.
380// If CXCursorKind == Cursor_Declaration, then this will return the declaration.
381CXDecl clang_getCursorDecl(CXCursor)
382{
383 return 0;
384}
385
386} // end extern "C"