2009-08-26 22:36:44 +00:00
|
|
|
//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the Clang-C Source Indexing library.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang-c/Index.h"
|
2009-08-28 15:28:48 +00:00
|
|
|
#include "clang/Index/Program.h"
|
|
|
|
#include "clang/Index/Indexer.h"
|
|
|
|
#include "clang/AST/DeclVisitor.h"
|
2009-08-29 12:56:35 +00:00
|
|
|
#include "clang/Basic/FileManager.h"
|
2009-08-31 14:26:51 +00:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2009-08-29 12:56:35 +00:00
|
|
|
#include "clang/Frontend/ASTUnit.h"
|
|
|
|
#include <cstdio>
|
2009-08-28 15:28:48 +00:00
|
|
|
using namespace clang;
|
|
|
|
using namespace idx;
|
|
|
|
|
2009-08-31 00:59:03 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
// Translation Unit Visitor.
|
|
|
|
class TUVisitor : public DeclVisitor<TUVisitor> {
|
|
|
|
CXTranslationUnit TUnit;
|
|
|
|
CXTranslationUnitIterator Callback;
|
2009-09-01 15:55:40 +00:00
|
|
|
CXClientData CData;
|
|
|
|
|
|
|
|
void Call(enum CXCursorKind CK, NamedDecl *ND) {
|
|
|
|
CXCursor C = { CK, ND };
|
|
|
|
Callback(TUnit, C, CData);
|
|
|
|
}
|
2009-08-31 00:59:03 +00:00
|
|
|
public:
|
2009-09-01 15:55:40 +00:00
|
|
|
TUVisitor(CXTranslationUnit CTU,
|
|
|
|
CXTranslationUnitIterator cback, CXClientData D) :
|
|
|
|
TUnit(CTU), Callback(cback), CData(D) {}
|
2009-08-31 00:59:03 +00:00
|
|
|
|
|
|
|
void VisitTranslationUnitDecl(TranslationUnitDecl *D) {
|
|
|
|
VisitDeclContext(dyn_cast<DeclContext>(D));
|
|
|
|
}
|
|
|
|
void VisitDeclContext(DeclContext *DC) {
|
|
|
|
for (DeclContext::decl_iterator
|
|
|
|
I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
|
|
|
|
Visit(*I);
|
|
|
|
}
|
2009-09-01 15:55:40 +00:00
|
|
|
void VisitTypedefDecl(TypedefDecl *ND) {
|
|
|
|
Call(CXCursor_TypedefDecl, ND);
|
2009-08-31 00:59:03 +00:00
|
|
|
}
|
|
|
|
void VisitTagDecl(TagDecl *ND) {
|
2009-09-01 15:55:40 +00:00
|
|
|
Call(ND->isEnum() ? CXCursor_EnumDecl : CXCursor_RecordDecl, ND);
|
2009-08-31 00:59:03 +00:00
|
|
|
}
|
|
|
|
void VisitFunctionDecl(FunctionDecl *ND) {
|
2009-09-01 15:55:40 +00:00
|
|
|
Call(CXCursor_FunctionDecl, ND);
|
2009-08-31 00:59:03 +00:00
|
|
|
}
|
|
|
|
void VisitObjCInterfaceDecl(ObjCInterfaceDecl *ND) {
|
2009-09-01 15:55:40 +00:00
|
|
|
Call(CXCursor_ObjCInterfaceDecl, ND);
|
2009-08-31 00:59:03 +00:00
|
|
|
}
|
|
|
|
void VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
|
2009-09-01 15:55:40 +00:00
|
|
|
Call(CXCursor_ObjCCategoryDecl, ND);
|
2009-08-31 00:59:03 +00:00
|
|
|
}
|
|
|
|
void VisitObjCProtocolDecl(ObjCProtocolDecl *ND) {
|
2009-09-01 15:55:40 +00:00
|
|
|
Call(CXCursor_ObjCProtocolDecl, ND);
|
2009-08-31 00:59:03 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Top-level declaration visitor.
|
|
|
|
class TLDeclVisitor : public DeclVisitor<TLDeclVisitor> {
|
|
|
|
public:
|
|
|
|
void VisitDeclContext(DeclContext *DC) {
|
|
|
|
for (DeclContext::decl_iterator
|
|
|
|
I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
|
|
|
|
Visit(*I);
|
|
|
|
}
|
|
|
|
void VisitEnumConstantDecl(EnumConstantDecl *ND) {
|
|
|
|
}
|
|
|
|
void VisitFieldDecl(FieldDecl *ND) {
|
|
|
|
}
|
|
|
|
void VisitObjCIvarDecl(ObjCIvarDecl *ND) {
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-08-27 19:51:58 +00:00
|
|
|
extern "C" {
|
2009-08-26 22:36:44 +00:00
|
|
|
|
2009-08-27 19:51:58 +00:00
|
|
|
CXIndex clang_createIndex()
|
2009-08-28 15:28:48 +00:00
|
|
|
{
|
|
|
|
return new Indexer(*new Program(), *new FileManager());
|
2009-08-27 19:51:58 +00:00
|
|
|
}
|
|
|
|
|
2009-08-28 15:28:48 +00:00
|
|
|
// FIXME: need to pass back error info.
|
|
|
|
CXTranslationUnit clang_createTranslationUnit(
|
|
|
|
CXIndex CIdx, const char *ast_filename)
|
2009-08-27 19:51:58 +00:00
|
|
|
{
|
2009-08-28 15:28:48 +00:00
|
|
|
assert(CIdx && "Passed null CXIndex");
|
|
|
|
Indexer *CXXIdx = static_cast<Indexer *>(CIdx);
|
|
|
|
std::string astName(ast_filename);
|
|
|
|
std::string ErrMsg;
|
|
|
|
|
|
|
|
return ASTUnit::LoadFromPCHFile(astName, CXXIdx->getFileManager(), &ErrMsg);
|
2009-08-27 19:51:58 +00:00
|
|
|
}
|
|
|
|
|
2009-08-28 16:30:07 +00:00
|
|
|
|
2009-08-27 19:51:58 +00:00
|
|
|
void clang_loadTranslationUnit(
|
2009-09-01 15:55:40 +00:00
|
|
|
CXTranslationUnit CTUnit, CXTranslationUnitIterator callback,
|
|
|
|
CXClientData CData)
|
2009-08-27 19:51:58 +00:00
|
|
|
{
|
2009-08-28 15:28:48 +00:00
|
|
|
assert(CTUnit && "Passed null CXTranslationUnit");
|
|
|
|
ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
|
|
|
|
ASTContext &Ctx = CXXUnit->getASTContext();
|
|
|
|
|
2009-09-01 15:55:40 +00:00
|
|
|
TUVisitor DVisit(CTUnit, callback, CData);
|
2009-08-28 15:28:48 +00:00
|
|
|
DVisit.Visit(Ctx.getTranslationUnitDecl());
|
2009-08-27 19:51:58 +00:00
|
|
|
}
|
|
|
|
|
2009-08-31 00:59:03 +00:00
|
|
|
void clang_loadDeclaration(CXDecl, CXDeclIterator)
|
2009-08-27 19:51:58 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-08-28 12:07:44 +00:00
|
|
|
// Some notes on CXEntity:
|
|
|
|
//
|
|
|
|
// - Since the 'ordinary' namespace includes functions, data, typedefs,
|
|
|
|
// ObjC interfaces, thecurrent algorithm is a bit naive (resulting in one
|
|
|
|
// entity for 2 different types). For example:
|
|
|
|
//
|
|
|
|
// module1.m: @interface Foo @end Foo *x;
|
|
|
|
// module2.m: void Foo(int);
|
|
|
|
//
|
|
|
|
// - Since the unique name spans translation units, static data/functions
|
|
|
|
// within a CXTranslationUnit are *not* currently represented by entities.
|
|
|
|
// As a result, there will be no entity for the following:
|
|
|
|
//
|
|
|
|
// module.m: static void Foo() { }
|
|
|
|
//
|
|
|
|
|
|
|
|
|
2009-08-27 19:51:58 +00:00
|
|
|
const char *clang_getDeclarationName(CXEntity)
|
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
const char *clang_getURI(CXEntity)
|
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
CXEntity clang_getEntity(const char *URI)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// CXDecl Operations.
|
|
|
|
//
|
|
|
|
CXCursor clang_getCursorFromDecl(CXDecl)
|
|
|
|
{
|
2009-08-31 00:59:03 +00:00
|
|
|
return CXCursor();
|
2009-08-27 19:51:58 +00:00
|
|
|
}
|
|
|
|
CXEntity clang_getEntityFromDecl(CXDecl)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2009-08-31 00:59:03 +00:00
|
|
|
const char *clang_getDeclSpelling(CXDecl AnonDecl)
|
|
|
|
{
|
|
|
|
assert(AnonDecl && "Passed null CXDecl");
|
|
|
|
NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
|
|
|
|
if (ND->getIdentifier())
|
|
|
|
return ND->getIdentifier()->getName();
|
|
|
|
else
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
const char *clang_getKindSpelling(enum CXCursorKind Kind)
|
|
|
|
{
|
|
|
|
switch (Kind) {
|
|
|
|
case CXCursor_FunctionDecl: return "FunctionDecl";
|
|
|
|
case CXCursor_TypedefDecl: return "TypedefDecl";
|
|
|
|
case CXCursor_EnumDecl: return "EnumDecl";
|
|
|
|
case CXCursor_EnumConstantDecl: return "EnumConstantDecl";
|
|
|
|
case CXCursor_RecordDecl: return "RecordDecl";
|
|
|
|
case CXCursor_FieldDecl: return "FieldDecl";
|
|
|
|
case CXCursor_VarDecl: return "VarDecl";
|
|
|
|
case CXCursor_ParmDecl: return "ParmDecl";
|
|
|
|
case CXCursor_ObjCInterfaceDecl: return "ObjCInterfaceDecl";
|
|
|
|
case CXCursor_ObjCCategoryDecl: return "ObjCCategoryDecl";
|
|
|
|
case CXCursor_ObjCProtocolDecl: return "ObjCProtocolDecl";
|
|
|
|
case CXCursor_ObjCPropertyDecl: return "ObjCPropertyDecl";
|
|
|
|
case CXCursor_ObjCIvarDecl: return "ObjCIvarDecl";
|
|
|
|
case CXCursor_ObjCMethodDecl: return "ObjCMethodDecl";
|
|
|
|
default: return "<not implemented>";
|
|
|
|
}
|
2009-08-27 19:51:58 +00:00
|
|
|
}
|
2009-08-31 00:59:03 +00:00
|
|
|
|
2009-08-27 19:51:58 +00:00
|
|
|
//
|
|
|
|
// CXCursor Operations.
|
|
|
|
//
|
|
|
|
CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
|
|
|
|
unsigned line, unsigned column)
|
|
|
|
{
|
2009-08-31 00:59:03 +00:00
|
|
|
return CXCursor();
|
2009-08-27 19:51:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CXCursorKind clang_getCursorKind(CXCursor)
|
|
|
|
{
|
2009-08-31 00:59:03 +00:00
|
|
|
return CXCursor_Invalid;
|
2009-08-27 19:51:58 +00:00
|
|
|
}
|
|
|
|
|
2009-08-31 00:59:03 +00:00
|
|
|
unsigned clang_isDeclaration(enum CXCursorKind K)
|
|
|
|
{
|
|
|
|
return K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl;
|
|
|
|
}
|
2009-08-31 14:26:51 +00:00
|
|
|
|
|
|
|
unsigned clang_getCursorLine(CXCursor C)
|
|
|
|
{
|
|
|
|
assert(C.decl && "CXCursor has null decl");
|
|
|
|
NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
|
|
|
|
SourceLocation SLoc = ND->getLocation();
|
|
|
|
if (SLoc.isInvalid())
|
|
|
|
return 0;
|
|
|
|
SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
|
|
|
|
SLoc = SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
|
|
|
|
return SourceMgr.getSpellingLineNumber(SLoc);
|
|
|
|
}
|
|
|
|
unsigned clang_getCursorColumn(CXCursor C)
|
|
|
|
{
|
|
|
|
assert(C.decl && "CXCursor has null decl");
|
|
|
|
NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
|
|
|
|
SourceLocation SLoc = ND->getLocation();
|
|
|
|
if (SLoc.isInvalid())
|
|
|
|
return 0;
|
|
|
|
SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
|
|
|
|
SLoc = SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
|
|
|
|
return SourceMgr.getSpellingColumnNumber(SLoc);
|
|
|
|
}
|
|
|
|
const char *clang_getCursorSource(CXCursor C)
|
|
|
|
{
|
|
|
|
assert(C.decl && "CXCursor has null decl");
|
|
|
|
NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
|
|
|
|
SourceLocation SLoc = ND->getLocation();
|
|
|
|
if (SLoc.isInvalid())
|
|
|
|
return "<invalid source location>";
|
|
|
|
SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
|
|
|
|
SLoc = SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
|
|
|
|
return SourceMgr.getBufferName(SLoc);
|
2009-08-27 19:51:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If CXCursorKind == Cursor_Reference, then this will return the referenced declaration.
|
|
|
|
// If CXCursorKind == Cursor_Declaration, then this will return the declaration.
|
|
|
|
CXDecl clang_getCursorDecl(CXCursor)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end extern "C"
|