blob: 5242de2360f6fe1f61a8570e77de3df2d462b824 [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) {
106 VisitDeclContext(dyn_cast<DeclContext>(D));
107 }
108 void VisitTagDecl(TagDecl *D) {
109 VisitDeclContext(dyn_cast<DeclContext>(D));
110 }
111 void VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
112 VisitDeclContext(dyn_cast<DeclContext>(D));
113 }
114 void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
115 VisitDeclContext(dyn_cast<DeclContext>(D));
116 }
Steve Naroff89922f82009-08-31 00:59:03 +0000117 void VisitDeclContext(DeclContext *DC) {
118 for (DeclContext::decl_iterator
119 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
120 Visit(*I);
121 }
122 void VisitEnumConstantDecl(EnumConstantDecl *ND) {
Steve Naroffc857ea42009-09-02 13:28:54 +0000123 Call(CXCursor_EnumConstantDecl, ND);
Steve Naroff89922f82009-08-31 00:59:03 +0000124 }
125 void VisitFieldDecl(FieldDecl *ND) {
Steve Naroffc857ea42009-09-02 13:28:54 +0000126 Call(CXCursor_FieldDecl, ND);
127 }
128 void VisitObjCPropertyDecl(ObjCPropertyDecl *ND) {
129 Call(CXCursor_ObjCPropertyDecl, ND);
Steve Naroff89922f82009-08-31 00:59:03 +0000130 }
131 void VisitObjCIvarDecl(ObjCIvarDecl *ND) {
Steve Naroffc857ea42009-09-02 13:28:54 +0000132 Call(CXCursor_ObjCIvarDecl, ND);
133 }
134 void VisitObjCMethodDecl(ObjCMethodDecl *ND) {
135 if (ND->getBody()) {
136 Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDefn
137 : CXCursor_ObjCClassMethodDefn, ND);
138 // FIXME: load body.
139 } else
140 Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl
141 : CXCursor_ObjCClassMethodDecl, ND);
Steve Naroff89922f82009-08-31 00:59:03 +0000142 }
143};
144
145}
146
Steve Naroff600866c2009-08-27 19:51:58 +0000147extern "C" {
Ted Kremenekd2fa5662009-08-26 22:36:44 +0000148
Steve Naroff600866c2009-08-27 19:51:58 +0000149CXIndex clang_createIndex()
Steve Naroff50398192009-08-28 15:28:48 +0000150{
151 return new Indexer(*new Program(), *new FileManager());
Steve Naroff600866c2009-08-27 19:51:58 +0000152}
153
Steve Naroff50398192009-08-28 15:28:48 +0000154// FIXME: need to pass back error info.
155CXTranslationUnit clang_createTranslationUnit(
156 CXIndex CIdx, const char *ast_filename)
Steve Naroff600866c2009-08-27 19:51:58 +0000157{
Steve Naroff50398192009-08-28 15:28:48 +0000158 assert(CIdx && "Passed null CXIndex");
159 Indexer *CXXIdx = static_cast<Indexer *>(CIdx);
160 std::string astName(ast_filename);
161 std::string ErrMsg;
162
163 return ASTUnit::LoadFromPCHFile(astName, CXXIdx->getFileManager(), &ErrMsg);
Steve Naroff600866c2009-08-27 19:51:58 +0000164}
165
Daniel Dunbar1eb79b52009-08-28 16:30:07 +0000166
Steve Naroffc857ea42009-09-02 13:28:54 +0000167void clang_loadTranslationUnit(CXTranslationUnit CTUnit,
168 CXTranslationUnitIterator callback,
169 CXClientData CData)
Steve Naroff600866c2009-08-27 19:51:58 +0000170{
Steve Naroff50398192009-08-28 15:28:48 +0000171 assert(CTUnit && "Passed null CXTranslationUnit");
172 ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
173 ASTContext &Ctx = CXXUnit->getASTContext();
174
Steve Naroff2b8ee6c2009-09-01 15:55:40 +0000175 TUVisitor DVisit(CTUnit, callback, CData);
Steve Naroff50398192009-08-28 15:28:48 +0000176 DVisit.Visit(Ctx.getTranslationUnitDecl());
Steve Naroff600866c2009-08-27 19:51:58 +0000177}
178
Steve Naroffc857ea42009-09-02 13:28:54 +0000179void clang_loadDeclaration(CXDecl Dcl,
180 CXDeclIterator callback,
181 CXClientData CData)
Steve Naroff600866c2009-08-27 19:51:58 +0000182{
Steve Naroffc857ea42009-09-02 13:28:54 +0000183 assert(Dcl && "Passed null CXDecl");
184
185 CDeclVisitor DVisit(Dcl, callback, CData);
186 DVisit.Visit(static_cast<Decl *>(Dcl));
Steve Naroff600866c2009-08-27 19:51:58 +0000187}
188
Steve Naroff7e8f8182009-08-28 12:07:44 +0000189// Some notes on CXEntity:
190//
191// - Since the 'ordinary' namespace includes functions, data, typedefs,
192// ObjC interfaces, thecurrent algorithm is a bit naive (resulting in one
193// entity for 2 different types). For example:
194//
195// module1.m: @interface Foo @end Foo *x;
196// module2.m: void Foo(int);
197//
198// - Since the unique name spans translation units, static data/functions
199// within a CXTranslationUnit are *not* currently represented by entities.
200// As a result, there will be no entity for the following:
201//
202// module.m: static void Foo() { }
203//
204
205
Steve Naroff600866c2009-08-27 19:51:58 +0000206const char *clang_getDeclarationName(CXEntity)
207{
208 return "";
209}
210const char *clang_getURI(CXEntity)
211{
212 return "";
213}
214
215CXEntity clang_getEntity(const char *URI)
216{
217 return 0;
218}
219
220//
221// CXDecl Operations.
222//
223CXCursor clang_getCursorFromDecl(CXDecl)
224{
Steve Naroff89922f82009-08-31 00:59:03 +0000225 return CXCursor();
Steve Naroff600866c2009-08-27 19:51:58 +0000226}
227CXEntity clang_getEntityFromDecl(CXDecl)
228{
229 return 0;
230}
Steve Naroff89922f82009-08-31 00:59:03 +0000231const char *clang_getDeclSpelling(CXDecl AnonDecl)
Steve Naroff600866c2009-08-27 19:51:58 +0000232{
Steve Naroff89922f82009-08-31 00:59:03 +0000233 assert(AnonDecl && "Passed null CXDecl");
234 NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
Steve Naroffc857ea42009-09-02 13:28:54 +0000235
236 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND)) {
237 return OMD->getSelector().getAsString().c_str();
238 }
Steve Naroff89922f82009-08-31 00:59:03 +0000239 if (ND->getIdentifier())
240 return ND->getIdentifier()->getName();
Steve Naroffc857ea42009-09-02 13:28:54 +0000241 else
Steve Naroff89922f82009-08-31 00:59:03 +0000242 return "";
Steve Naroff600866c2009-08-27 19:51:58 +0000243}
Steve Naroff89922f82009-08-31 00:59:03 +0000244const char *clang_getKindSpelling(enum CXCursorKind Kind)
Steve Naroff600866c2009-08-27 19:51:58 +0000245{
Steve Naroff89922f82009-08-31 00:59:03 +0000246 switch (Kind) {
247 case CXCursor_FunctionDecl: return "FunctionDecl";
248 case CXCursor_TypedefDecl: return "TypedefDecl";
249 case CXCursor_EnumDecl: return "EnumDecl";
250 case CXCursor_EnumConstantDecl: return "EnumConstantDecl";
Steve Naroffc857ea42009-09-02 13:28:54 +0000251 case CXCursor_StructDecl: return "StructDecl";
252 case CXCursor_UnionDecl: return "UnionDecl";
253 case CXCursor_ClassDecl: return "ClassDecl";
Steve Naroff89922f82009-08-31 00:59:03 +0000254 case CXCursor_FieldDecl: return "FieldDecl";
255 case CXCursor_VarDecl: return "VarDecl";
256 case CXCursor_ParmDecl: return "ParmDecl";
257 case CXCursor_ObjCInterfaceDecl: return "ObjCInterfaceDecl";
258 case CXCursor_ObjCCategoryDecl: return "ObjCCategoryDecl";
259 case CXCursor_ObjCProtocolDecl: return "ObjCProtocolDecl";
260 case CXCursor_ObjCPropertyDecl: return "ObjCPropertyDecl";
261 case CXCursor_ObjCIvarDecl: return "ObjCIvarDecl";
Steve Naroffc857ea42009-09-02 13:28:54 +0000262 case CXCursor_ObjCInstanceMethodDecl: return "ObjCInstanceMethodDecl";
263 case CXCursor_ObjCClassMethodDecl: return "ObjCClassMethodDecl";
264 case CXCursor_FunctionDefn: return "FunctionDefn";
265 case CXCursor_ObjCInstanceMethodDefn: return "ObjCInstanceMethodDefn";
266 case CXCursor_ObjCClassMethodDefn: return "ObjCClassMethodDefn";
267 case CXCursor_ObjCClassDefn: return "ObjCClassDefn";
268 case CXCursor_ObjCCategoryDefn: return "ObjCCategoryDefn";
Steve Naroff89922f82009-08-31 00:59:03 +0000269 default: return "<not implemented>";
270 }
Steve Naroff600866c2009-08-27 19:51:58 +0000271}
Steve Naroff89922f82009-08-31 00:59:03 +0000272
Steve Naroff600866c2009-08-27 19:51:58 +0000273//
274// CXCursor Operations.
275//
276CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
277 unsigned line, unsigned column)
278{
Steve Naroff89922f82009-08-31 00:59:03 +0000279 return CXCursor();
Steve Naroff600866c2009-08-27 19:51:58 +0000280}
281
282CXCursorKind clang_getCursorKind(CXCursor)
283{
Steve Naroff89922f82009-08-31 00:59:03 +0000284 return CXCursor_Invalid;
Steve Naroff600866c2009-08-27 19:51:58 +0000285}
286
Steve Naroff89922f82009-08-31 00:59:03 +0000287unsigned clang_isDeclaration(enum CXCursorKind K)
288{
289 return K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl;
290}
Steve Naroff2d4d6292009-08-31 14:26:51 +0000291
292unsigned clang_getCursorLine(CXCursor C)
Steve Naroff600866c2009-08-27 19:51:58 +0000293{
Steve Naroff2d4d6292009-08-31 14:26:51 +0000294 assert(C.decl && "CXCursor has null decl");
295 NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
296 SourceLocation SLoc = ND->getLocation();
297 if (SLoc.isInvalid())
298 return 0;
299 SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
300 SLoc = SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
301 return SourceMgr.getSpellingLineNumber(SLoc);
Steve Naroff600866c2009-08-27 19:51:58 +0000302}
Steve Naroff2d4d6292009-08-31 14:26:51 +0000303unsigned clang_getCursorColumn(CXCursor C)
Steve Naroff600866c2009-08-27 19:51:58 +0000304{
Steve Naroff2d4d6292009-08-31 14:26:51 +0000305 assert(C.decl && "CXCursor has null decl");
306 NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
307 SourceLocation SLoc = ND->getLocation();
308 if (SLoc.isInvalid())
309 return 0;
310 SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
311 SLoc = SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
312 return SourceMgr.getSpellingColumnNumber(SLoc);
Steve Naroff600866c2009-08-27 19:51:58 +0000313}
Steve Naroff2d4d6292009-08-31 14:26:51 +0000314const char *clang_getCursorSource(CXCursor C)
Steve Naroff600866c2009-08-27 19:51:58 +0000315{
Steve Naroff2d4d6292009-08-31 14:26:51 +0000316 assert(C.decl && "CXCursor has null decl");
317 NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
318 SourceLocation SLoc = ND->getLocation();
319 if (SLoc.isInvalid())
320 return "<invalid source location>";
321 SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
322 SLoc = SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
323 return SourceMgr.getBufferName(SLoc);
Steve Naroff600866c2009-08-27 19:51:58 +0000324}
325
326// If CXCursorKind == Cursor_Reference, then this will return the referenced declaration.
327// If CXCursorKind == Cursor_Declaration, then this will return the declaration.
328CXDecl clang_getCursorDecl(CXCursor)
329{
330 return 0;
331}
332
333} // end extern "C"