mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 15:16:08 +00:00
[libclang] Separate the underlying indexing functionality of libclang and introduce it into the clangIndex library.
It is a general goodness for libclang itself to mostly be a wrapper of functionality provided by the libraries. llvm-svn: 260760
This commit is contained in:
parent
51699a83cd
commit
f4fb85b1c7
61
clang/include/clang/Index/IndexDataConsumer.h
Normal file
61
clang/include/clang/Index/IndexDataConsumer.h
Normal file
@ -0,0 +1,61 @@
|
||||
//===--- IndexDataConsumer.h - Abstract index data consumer ---------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_INDEXDATACONSUMER_H
|
||||
#define LLVM_CLANG_INDEX_INDEXDATACONSUMER_H
|
||||
|
||||
#include "clang/Index/IndexSymbol.h"
|
||||
|
||||
namespace clang {
|
||||
class DeclContext;
|
||||
class Expr;
|
||||
class FileID;
|
||||
class IdentifierInfo;
|
||||
class ImportDecl;
|
||||
class MacroInfo;
|
||||
|
||||
namespace index {
|
||||
|
||||
class IndexDataConsumer {
|
||||
public:
|
||||
struct ASTNodeInfo {
|
||||
const Expr *OrigE;
|
||||
const Decl *OrigD;
|
||||
const Decl *Parent;
|
||||
const DeclContext *ContainerDC;
|
||||
};
|
||||
|
||||
virtual ~IndexDataConsumer() {}
|
||||
|
||||
/// \returns true to continue indexing, or false to abort.
|
||||
virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
|
||||
ArrayRef<SymbolRelation> Relations,
|
||||
FileID FID, unsigned Offset,
|
||||
ASTNodeInfo ASTNode);
|
||||
|
||||
/// \returns true to continue indexing, or false to abort.
|
||||
virtual bool handleMacroOccurence(const IdentifierInfo *Name,
|
||||
const MacroInfo *MI, SymbolRoleSet Roles,
|
||||
FileID FID, unsigned Offset);
|
||||
|
||||
/// \returns true to continue indexing, or false to abort.
|
||||
virtual bool handleModuleOccurence(const ImportDecl *ImportD,
|
||||
SymbolRoleSet Roles,
|
||||
FileID FID, unsigned Offset);
|
||||
|
||||
virtual void finish() {}
|
||||
|
||||
private:
|
||||
virtual void _anchor();
|
||||
};
|
||||
|
||||
} // namespace index
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
112
clang/include/clang/Index/IndexSymbol.h
Normal file
112
clang/include/clang/Index/IndexSymbol.h
Normal file
@ -0,0 +1,112 @@
|
||||
//===--- IndexSymbol.h - Types and functions for indexing symbols ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_INDEXSYMBOL_H
|
||||
#define LLVM_CLANG_INDEX_INDEXSYMBOL_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
|
||||
namespace clang {
|
||||
class Decl;
|
||||
|
||||
namespace index {
|
||||
|
||||
enum class SymbolKind : uint8_t {
|
||||
Unknown,
|
||||
|
||||
Module,
|
||||
Macro,
|
||||
|
||||
Enum,
|
||||
Struct,
|
||||
Union,
|
||||
Typedef,
|
||||
|
||||
Function,
|
||||
Variable,
|
||||
Field,
|
||||
EnumConstant,
|
||||
|
||||
ObjCClass,
|
||||
ObjCProtocol,
|
||||
ObjCCategory,
|
||||
|
||||
ObjCInstanceMethod,
|
||||
ObjCClassMethod,
|
||||
ObjCProperty,
|
||||
ObjCIvar,
|
||||
|
||||
CXXClass,
|
||||
CXXNamespace,
|
||||
CXXNamespaceAlias,
|
||||
CXXStaticVariable,
|
||||
CXXStaticMethod,
|
||||
CXXInstanceMethod,
|
||||
CXXConstructor,
|
||||
CXXDestructor,
|
||||
CXXConversionFunction,
|
||||
CXXTypeAlias,
|
||||
CXXInterface,
|
||||
};
|
||||
|
||||
enum class SymbolLanguage {
|
||||
C,
|
||||
ObjC,
|
||||
CXX,
|
||||
};
|
||||
|
||||
enum class SymbolCXXTemplateKind {
|
||||
NonTemplate,
|
||||
Template,
|
||||
TemplatePartialSpecialization,
|
||||
TemplateSpecialization,
|
||||
};
|
||||
|
||||
/// Set of roles that are attributed to symbol occurrences.
|
||||
enum class SymbolRole : uint16_t {
|
||||
Declaration = 1 << 0,
|
||||
Definition = 1 << 1,
|
||||
Reference = 1 << 2,
|
||||
Read = 1 << 3,
|
||||
Write = 1 << 4,
|
||||
Call = 1 << 5,
|
||||
Dynamic = 1 << 6,
|
||||
AddressOf = 1 << 7,
|
||||
Implicit = 1 << 8,
|
||||
|
||||
// Relation roles.
|
||||
RelationChildOf = 1 << 9,
|
||||
RelationBaseOf = 1 << 10,
|
||||
RelationOverrideOf = 1 << 11,
|
||||
RelationReceivedBy = 1 << 12,
|
||||
};
|
||||
static const unsigned SymbolRoleBitNum = 13;
|
||||
typedef unsigned SymbolRoleSet;
|
||||
|
||||
/// Represents a relation to another symbol for a symbol occurrence.
|
||||
struct SymbolRelation {
|
||||
SymbolRoleSet Roles;
|
||||
const Decl *RelatedSymbol;
|
||||
|
||||
SymbolRelation(SymbolRoleSet Roles, const Decl *Sym)
|
||||
: Roles(Roles), RelatedSymbol(Sym) {}
|
||||
};
|
||||
|
||||
struct SymbolInfo {
|
||||
SymbolKind Kind;
|
||||
SymbolCXXTemplateKind TemplateKind;
|
||||
SymbolLanguage Lang;
|
||||
};
|
||||
|
||||
SymbolInfo getSymbolInfo(const Decl *D);
|
||||
|
||||
} // namespace index
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
47
clang/include/clang/Index/IndexingAction.h
Normal file
47
clang/include/clang/Index/IndexingAction.h
Normal file
@ -0,0 +1,47 @@
|
||||
//===--- IndexingAction.h - Frontend index action -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_INDEXINGACTION_H
|
||||
#define LLVM_CLANG_INDEX_INDEXINGACTION_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include <memory>
|
||||
|
||||
namespace clang {
|
||||
class ASTUnit;
|
||||
class FrontendAction;
|
||||
|
||||
namespace index {
|
||||
class IndexDataConsumer;
|
||||
|
||||
struct IndexingOptions {
|
||||
enum class SystemSymbolFilterKind {
|
||||
None,
|
||||
DeclarationsOnly,
|
||||
All,
|
||||
};
|
||||
|
||||
SystemSymbolFilterKind SystemSymbolFilter
|
||||
= SystemSymbolFilterKind::DeclarationsOnly;
|
||||
bool IndexFunctionLocals = false;
|
||||
};
|
||||
|
||||
std::unique_ptr<FrontendAction>
|
||||
createIndexingAction(std::unique_ptr<FrontendAction> WrappedAction,
|
||||
std::shared_ptr<IndexDataConsumer> DataConsumer,
|
||||
IndexingOptions Opts);
|
||||
|
||||
void indexASTUnit(ASTUnit &Unit,
|
||||
std::shared_ptr<IndexDataConsumer> DataConsumer,
|
||||
IndexingOptions Opts);
|
||||
|
||||
} // namespace index
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
@ -5,14 +5,22 @@ set(LLVM_LINK_COMPONENTS
|
||||
add_clang_library(clangIndex
|
||||
CommentToXML.cpp
|
||||
USRGeneration.cpp
|
||||
IndexBody.cpp
|
||||
IndexDecl.cpp
|
||||
IndexingAction.cpp
|
||||
IndexingContext.cpp
|
||||
IndexSymbol.cpp
|
||||
IndexTypeSourceInfo.cpp
|
||||
|
||||
ADDITIONAL_HEADERS
|
||||
IndexingContext.h
|
||||
SimpleFormatContext.h
|
||||
|
||||
LINK_LIBS
|
||||
clangAST
|
||||
clangBasic
|
||||
clangFormat
|
||||
clangFrontend
|
||||
clangRewrite
|
||||
clangToolingCore
|
||||
)
|
||||
|
347
clang/lib/Index/IndexBody.cpp
Normal file
347
clang/lib/Index/IndexBody.cpp
Normal file
@ -0,0 +1,347 @@
|
||||
//===- IndexBody.cpp - Indexing statements --------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IndexingContext.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::index;
|
||||
|
||||
namespace {
|
||||
|
||||
class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
|
||||
IndexingContext &IndexCtx;
|
||||
const NamedDecl *Parent;
|
||||
const DeclContext *ParentDC;
|
||||
SmallVector<Stmt*, 16> StmtStack;
|
||||
|
||||
typedef RecursiveASTVisitor<BodyIndexer> base;
|
||||
public:
|
||||
BodyIndexer(IndexingContext &indexCtx,
|
||||
const NamedDecl *Parent, const DeclContext *DC)
|
||||
: IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
|
||||
|
||||
bool shouldWalkTypesOfTypeLocs() const { return false; }
|
||||
|
||||
bool TraverseStmt(Stmt *S) {
|
||||
StmtStack.push_back(S);
|
||||
bool ret = base::TraverseStmt(S);
|
||||
StmtStack.pop_back();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TraverseTypeLoc(TypeLoc TL) {
|
||||
IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
|
||||
IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
|
||||
return true;
|
||||
}
|
||||
|
||||
SymbolRoleSet getRolesForRef(const Expr *E,
|
||||
SmallVectorImpl<SymbolRelation> &Relations) {
|
||||
SymbolRoleSet Roles{};
|
||||
assert(!StmtStack.empty() && E == StmtStack.back());
|
||||
if (StmtStack.size() == 1)
|
||||
return Roles;
|
||||
auto It = StmtStack.end()-2;
|
||||
while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
|
||||
if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
|
||||
if (ICE->getCastKind() == CK_LValueToRValue)
|
||||
Roles |= (unsigned)(unsigned)SymbolRole::Read;
|
||||
}
|
||||
if (It == StmtStack.begin())
|
||||
break;
|
||||
--It;
|
||||
}
|
||||
const Stmt *Parent = *It;
|
||||
|
||||
if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
|
||||
if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
|
||||
Roles |= (unsigned)SymbolRole::Write;
|
||||
|
||||
} else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
|
||||
if (UO->isIncrementDecrementOp()) {
|
||||
Roles |= (unsigned)SymbolRole::Read;
|
||||
Roles |= (unsigned)SymbolRole::Write;
|
||||
} else if (UO->getOpcode() == UO_AddrOf) {
|
||||
Roles |= (unsigned)SymbolRole::AddressOf;
|
||||
}
|
||||
|
||||
} else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
|
||||
if (CA->getLHS()->IgnoreParenCasts() == E) {
|
||||
Roles |= (unsigned)SymbolRole::Read;
|
||||
Roles |= (unsigned)SymbolRole::Write;
|
||||
}
|
||||
|
||||
} else if (auto CE = dyn_cast<CallExpr>(Parent)) {
|
||||
if (CE->getCallee()->IgnoreParenCasts() == E) {
|
||||
Roles |= (unsigned)SymbolRole::Call;
|
||||
if (auto *ME = dyn_cast<MemberExpr>(E)) {
|
||||
if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
|
||||
if (CXXMD->isVirtual() && !ME->hasQualifier()) {
|
||||
Roles |= (unsigned)SymbolRole::Dynamic;
|
||||
auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
|
||||
if (!BaseTy.isNull())
|
||||
if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
|
||||
Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
|
||||
CXXRD);
|
||||
}
|
||||
}
|
||||
} else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
|
||||
if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
|
||||
OverloadedOperatorKind Op = CXXOp->getOperator();
|
||||
if (Op == OO_Equal) {
|
||||
Roles |= (unsigned)SymbolRole::Write;
|
||||
} else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
|
||||
Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
|
||||
Op == OO_PlusPlus || Op == OO_MinusMinus) {
|
||||
Roles |= (unsigned)SymbolRole::Read;
|
||||
Roles |= (unsigned)SymbolRole::Write;
|
||||
} else if (Op == OO_Amp) {
|
||||
Roles |= (unsigned)SymbolRole::AddressOf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Roles;
|
||||
}
|
||||
|
||||
bool VisitDeclRefExpr(DeclRefExpr *E) {
|
||||
SmallVector<SymbolRelation, 4> Relations;
|
||||
SymbolRoleSet Roles = getRolesForRef(E, Relations);
|
||||
return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
|
||||
Parent, ParentDC, Roles, Relations, E);
|
||||
}
|
||||
|
||||
bool VisitMemberExpr(MemberExpr *E) {
|
||||
SourceLocation Loc = E->getMemberLoc();
|
||||
if (Loc.isInvalid())
|
||||
Loc = E->getLocStart();
|
||||
SmallVector<SymbolRelation, 4> Relations;
|
||||
SymbolRoleSet Roles = getRolesForRef(E, Relations);
|
||||
return IndexCtx.handleReference(E->getMemberDecl(), Loc,
|
||||
Parent, ParentDC, Roles, Relations, E);
|
||||
}
|
||||
|
||||
bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
|
||||
for (DesignatedInitExpr::reverse_designators_iterator
|
||||
D = E->designators_rbegin(), DEnd = E->designators_rend();
|
||||
D != DEnd; ++D) {
|
||||
if (D->isFieldDesignator())
|
||||
return IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
|
||||
Parent, ParentDC, SymbolRoleSet(),
|
||||
{}, E);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
|
||||
SmallVector<SymbolRelation, 4> Relations;
|
||||
SymbolRoleSet Roles = getRolesForRef(E, Relations);
|
||||
return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
|
||||
Parent, ParentDC, Roles, Relations, E);
|
||||
}
|
||||
|
||||
bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
|
||||
auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
|
||||
if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
|
||||
return false;
|
||||
if (auto *RecE = dyn_cast<ObjCMessageExpr>(
|
||||
MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
|
||||
if (RecE->getMethodFamily() == OMF_alloc)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if (ObjCMethodDecl *MD = E->getMethodDecl()) {
|
||||
SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
|
||||
if (E->isImplicit())
|
||||
Roles |= (unsigned)SymbolRole::Implicit;
|
||||
|
||||
SmallVector<SymbolRelation, 2> Relations;
|
||||
if (isDynamic(E)) {
|
||||
Roles |= (unsigned)SymbolRole::Dynamic;
|
||||
if (auto *RecD = E->getReceiverInterface())
|
||||
Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
|
||||
}
|
||||
|
||||
return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
|
||||
Parent, ParentDC, Roles, Relations, E);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
|
||||
if (E->isExplicitProperty())
|
||||
return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
|
||||
Parent, ParentDC, SymbolRoleSet(), {}, E);
|
||||
|
||||
// No need to do a handleReference for the objc method, because there will
|
||||
// be a message expr as part of PseudoObjectExpr.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
|
||||
return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
|
||||
Parent, ParentDC, SymbolRoleSet(), {}, E);
|
||||
}
|
||||
|
||||
bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
|
||||
return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
|
||||
Parent, ParentDC, SymbolRoleSet(), {}, E);
|
||||
}
|
||||
|
||||
bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
|
||||
if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
|
||||
SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
|
||||
Roles |= (unsigned)SymbolRole::Implicit;
|
||||
return IndexCtx.handleReference(MD, E->getLocStart(),
|
||||
Parent, ParentDC, Roles, {}, E);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
|
||||
if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
|
||||
SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
|
||||
Roles |= (unsigned)SymbolRole::Implicit;
|
||||
return IndexCtx.handleReference(MD, E->getLocStart(),
|
||||
Parent, ParentDC, Roles, {}, E);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
|
||||
if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
|
||||
SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
|
||||
Roles |= (unsigned)SymbolRole::Implicit;
|
||||
return IndexCtx.handleReference(MD, E->getLocStart(),
|
||||
Parent, ParentDC, Roles, {}, E);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitCXXConstructExpr(CXXConstructExpr *E) {
|
||||
return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
|
||||
Parent, ParentDC, (unsigned)SymbolRole::Call, {}, E);
|
||||
}
|
||||
|
||||
bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
|
||||
DataRecursionQueue *Q = nullptr) {
|
||||
if (E->getOperatorLoc().isInvalid())
|
||||
return true; // implicit.
|
||||
return base::TraverseCXXOperatorCallExpr(E);
|
||||
}
|
||||
|
||||
bool VisitDeclStmt(DeclStmt *S) {
|
||||
if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
|
||||
IndexCtx.indexDeclGroupRef(S->getDeclGroup());
|
||||
return true;
|
||||
}
|
||||
|
||||
DeclGroupRef DG = S->getDeclGroup();
|
||||
for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
|
||||
const Decl *D = *I;
|
||||
if (!D)
|
||||
continue;
|
||||
if (!IndexCtx.isFunctionLocalDecl(D))
|
||||
IndexCtx.indexTopLevelDecl(D);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
|
||||
if (C->capturesThis() || C->capturesVLAType())
|
||||
return true;
|
||||
|
||||
if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
|
||||
return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
|
||||
Parent, ParentDC, SymbolRoleSet());
|
||||
|
||||
// FIXME: Lambda init-captures.
|
||||
return true;
|
||||
}
|
||||
|
||||
// RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
|
||||
// the things that we visit. Make sure to only visit the semantic form.
|
||||
// Also visit things that are in the syntactic form but not the semantic one,
|
||||
// for example the indices in DesignatedInitExprs.
|
||||
bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
|
||||
|
||||
class SyntacticFormIndexer :
|
||||
public RecursiveASTVisitor<SyntacticFormIndexer> {
|
||||
IndexingContext &IndexCtx;
|
||||
const NamedDecl *Parent;
|
||||
const DeclContext *ParentDC;
|
||||
|
||||
public:
|
||||
SyntacticFormIndexer(IndexingContext &indexCtx,
|
||||
const NamedDecl *Parent, const DeclContext *DC)
|
||||
: IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
|
||||
|
||||
bool shouldWalkTypesOfTypeLocs() const { return false; }
|
||||
|
||||
bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
|
||||
for (DesignatedInitExpr::reverse_designators_iterator
|
||||
D = E->designators_rbegin(), DEnd = E->designators_rend();
|
||||
D != DEnd; ++D) {
|
||||
if (D->isFieldDesignator())
|
||||
return IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
|
||||
Parent, ParentDC, SymbolRoleSet(),
|
||||
{}, E);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
auto visitForm = [&](InitListExpr *Form) {
|
||||
for (Stmt *SubStmt : Form->children()) {
|
||||
if (!TraverseStmt(SubStmt))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
|
||||
InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
|
||||
|
||||
if (SemaForm) {
|
||||
// Visit things present in syntactic form but not the semantic form.
|
||||
if (SyntaxForm) {
|
||||
SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
|
||||
}
|
||||
return visitForm(SemaForm);
|
||||
}
|
||||
|
||||
// No semantic, try the syntactic.
|
||||
if (SyntaxForm) {
|
||||
return visitForm(SyntaxForm);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
|
||||
const DeclContext *DC) {
|
||||
if (!S)
|
||||
return;
|
||||
|
||||
if (!DC)
|
||||
DC = Parent->getLexicalDeclContext();
|
||||
BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
|
||||
//===- IndexDecl.cpp - Indexing declarations ------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -8,10 +8,11 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IndexingContext.h"
|
||||
#include "clang/Index/IndexDataConsumer.h"
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace cxindex;
|
||||
using namespace index;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -22,6 +23,13 @@ public:
|
||||
explicit IndexingDeclVisitor(IndexingContext &indexCtx)
|
||||
: IndexCtx(indexCtx) { }
|
||||
|
||||
bool Handled = true;
|
||||
|
||||
bool VisitDecl(const Decl *D) {
|
||||
Handled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Returns true if the given method has been defined explicitly by the
|
||||
/// user.
|
||||
static bool hasUserDefined(const ObjCMethodDecl *D,
|
||||
@ -35,25 +43,35 @@ public:
|
||||
const NamedDecl *Parent = nullptr) {
|
||||
if (!Parent) Parent = D;
|
||||
|
||||
if (!IndexCtx.shouldIndexFunctionLocalSymbols()) {
|
||||
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent);
|
||||
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
|
||||
} else {
|
||||
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent);
|
||||
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
|
||||
if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
|
||||
// Only index parameters in definitions, parameters in declarations are
|
||||
// not useful.
|
||||
if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
|
||||
IndexCtx.handleVar(Parm);
|
||||
auto *DC = Parm->getDeclContext();
|
||||
if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
|
||||
if (FD->isThisDeclarationADefinition())
|
||||
IndexCtx.handleDecl(Parm);
|
||||
} else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
|
||||
if (MD->isThisDeclarationADefinition())
|
||||
IndexCtx.handleDecl(Parm);
|
||||
} else {
|
||||
IndexCtx.handleDecl(Parm);
|
||||
}
|
||||
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
for (auto PI : FD->params()) {
|
||||
IndexCtx.handleVar(PI);
|
||||
if (FD->isThisDeclarationADefinition()) {
|
||||
for (auto PI : FD->params()) {
|
||||
IndexCtx.handleDecl(PI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleObjCMethod(const ObjCMethodDecl *D) {
|
||||
IndexCtx.handleObjCMethod(D);
|
||||
if (D->isImplicit())
|
||||
return;
|
||||
|
||||
bool handleObjCMethod(const ObjCMethodDecl *D) {
|
||||
if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic))
|
||||
return false;
|
||||
IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
|
||||
for (const auto *I : D->params())
|
||||
handleDeclarator(I, D);
|
||||
@ -64,10 +82,26 @@ public:
|
||||
IndexCtx.indexBody(Body, D, D);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitFunctionDecl(const FunctionDecl *D) {
|
||||
IndexCtx.handleFunction(D);
|
||||
if (D->isDeleted())
|
||||
return true;
|
||||
|
||||
SymbolRoleSet Roles{};
|
||||
SmallVector<SymbolRelation, 4> Relations;
|
||||
if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
|
||||
if (CXXMD->isVirtual())
|
||||
Roles |= (unsigned)SymbolRole::Dynamic;
|
||||
for (auto I = CXXMD->begin_overridden_methods(),
|
||||
E = CXXMD->end_overridden_methods(); I != E; ++I) {
|
||||
Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IndexCtx.handleDecl(D, Roles, Relations))
|
||||
return false;
|
||||
handleDeclarator(D);
|
||||
|
||||
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
|
||||
@ -76,7 +110,8 @@ public:
|
||||
if (Init->isWritten()) {
|
||||
IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
|
||||
if (const FieldDecl *Member = Init->getAnyMember())
|
||||
IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D);
|
||||
IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
|
||||
(unsigned)SymbolRole::Write);
|
||||
IndexCtx.indexBody(Init->getInit(), D, D);
|
||||
}
|
||||
}
|
||||
@ -92,14 +127,16 @@ public:
|
||||
}
|
||||
|
||||
bool VisitVarDecl(const VarDecl *D) {
|
||||
IndexCtx.handleVar(D);
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
handleDeclarator(D);
|
||||
IndexCtx.indexBody(D->getInit(), D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitFieldDecl(const FieldDecl *D) {
|
||||
IndexCtx.handleField(D);
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
handleDeclarator(D);
|
||||
if (D->isBitField())
|
||||
IndexCtx.indexBody(D->getBitWidth(), D);
|
||||
@ -108,44 +145,77 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
|
||||
if (D->getSynthesize()) {
|
||||
// For synthesized ivars, use the location of the ObjC implementation,
|
||||
// not the location of the property.
|
||||
// Otherwise the header file containing the @interface will have different
|
||||
// indexing contents based on whether the @implementation was present or
|
||||
// not in the translation unit.
|
||||
return IndexCtx.handleDecl(D,
|
||||
cast<Decl>(D->getDeclContext())->getLocation(),
|
||||
(unsigned)SymbolRole::Implicit);
|
||||
}
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
handleDeclarator(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
|
||||
handleDeclarator(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
|
||||
IndexCtx.handleEnumerator(D);
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
IndexCtx.indexBody(D->getInitExpr(), D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
|
||||
IndexCtx.handleTypedefName(D);
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitTagDecl(const TagDecl *D) {
|
||||
// Non-free standing tags are handled in indexTypeSourceInfo.
|
||||
if (D->isFreeStanding())
|
||||
IndexCtx.indexTagDecl(D);
|
||||
if (D->isFreeStanding()) {
|
||||
if (D->isThisDeclarationADefinition()) {
|
||||
IndexCtx.indexTagDecl(D);
|
||||
} else {
|
||||
auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
|
||||
return IndexCtx.handleReference(D, D->getLocation(), Parent,
|
||||
D->getLexicalDeclContext(),
|
||||
SymbolRoleSet());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
|
||||
IndexCtx.handleObjCInterface(D);
|
||||
|
||||
if (D->isThisDeclarationADefinition()) {
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
IndexCtx.indexDeclContext(D);
|
||||
} else {
|
||||
return IndexCtx.handleReference(D, D->getLocation(), nullptr, nullptr,
|
||||
SymbolRoleSet());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
|
||||
IndexCtx.handleObjCProtocol(D);
|
||||
|
||||
if (D->isThisDeclarationADefinition()) {
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
IndexCtx.indexDeclContext(D);
|
||||
} else {
|
||||
return IndexCtx.handleReference(D, D->getLocation(), nullptr, nullptr,
|
||||
SymbolRoleSet());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -156,9 +226,10 @@ public:
|
||||
return true;
|
||||
|
||||
if (Class->isImplicitInterfaceDecl())
|
||||
IndexCtx.handleObjCInterface(Class);
|
||||
IndexCtx.handleDecl(Class);
|
||||
|
||||
IndexCtx.handleObjCImplementation(D);
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
|
||||
// Index the ivars first to make sure the synthesized ivars are indexed
|
||||
// before indexing the methods that can reference them.
|
||||
@ -173,7 +244,8 @@ public:
|
||||
}
|
||||
|
||||
bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
|
||||
IndexCtx.handleObjCCategory(D);
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
IndexCtx.indexDeclContext(D);
|
||||
return true;
|
||||
}
|
||||
@ -183,7 +255,8 @@ public:
|
||||
if (!Cat)
|
||||
return true;
|
||||
|
||||
IndexCtx.handleObjCCategoryImpl(D);
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
IndexCtx.indexDeclContext(D);
|
||||
return true;
|
||||
}
|
||||
@ -205,14 +278,19 @@ public:
|
||||
if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
|
||||
if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
|
||||
handleObjCMethod(MD);
|
||||
IndexCtx.handleObjCProperty(D);
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
|
||||
ObjCPropertyDecl *PD = D->getPropertyDecl();
|
||||
IndexCtx.handleSynthesizedObjCProperty(D);
|
||||
if (!IndexCtx.handleReference(PD, D->getLocation(),
|
||||
/*Parent=*/cast<NamedDecl>(D->getDeclContext()),
|
||||
D->getDeclContext(), SymbolRoleSet(), {},
|
||||
/*RefE=*/nullptr, D))
|
||||
return false;
|
||||
|
||||
if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
|
||||
return true;
|
||||
@ -221,121 +299,131 @@ public:
|
||||
if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
|
||||
if (!IvarD->getSynthesize())
|
||||
IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
|
||||
D->getDeclContext());
|
||||
D->getDeclContext(), SymbolRoleSet());
|
||||
}
|
||||
|
||||
auto *ImplD = cast<ObjCImplDecl>(D->getDeclContext());
|
||||
if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
|
||||
if (MD->isPropertyAccessor() &&
|
||||
!hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext())))
|
||||
IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(),
|
||||
D->getLexicalDeclContext());
|
||||
!hasUserDefined(MD, ImplD))
|
||||
IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD);
|
||||
}
|
||||
if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
|
||||
if (MD->isPropertyAccessor() &&
|
||||
!hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext())))
|
||||
IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(),
|
||||
D->getLexicalDeclContext());
|
||||
!hasUserDefined(MD, ImplD))
|
||||
IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitNamespaceDecl(const NamespaceDecl *D) {
|
||||
IndexCtx.handleNamespace(D);
|
||||
if (!IndexCtx.handleDecl(D))
|
||||
return false;
|
||||
IndexCtx.indexDeclContext(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitUsingDecl(const UsingDecl *D) {
|
||||
// FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
|
||||
// we should do better.
|
||||
const DeclContext *DC = D->getDeclContext()->getRedeclContext();
|
||||
const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
|
||||
|
||||
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
|
||||
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
|
||||
D->getLexicalDeclContext());
|
||||
for (const auto *I : D->shadows())
|
||||
IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), D,
|
||||
D->getLexicalDeclContext());
|
||||
IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
|
||||
D->getLexicalDeclContext(), SymbolRoleSet());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
|
||||
// FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR,
|
||||
// we should do better.
|
||||
const DeclContext *DC = D->getDeclContext()->getRedeclContext();
|
||||
const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
|
||||
|
||||
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
|
||||
IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
|
||||
D->getLocation(), D, D->getLexicalDeclContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitClassTemplateDecl(const ClassTemplateDecl *D) {
|
||||
IndexCtx.handleClassTemplate(D);
|
||||
if (D->isThisDeclarationADefinition())
|
||||
IndexCtx.indexDeclContext(D->getTemplatedDecl());
|
||||
return true;
|
||||
IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
|
||||
D->getLexicalDeclContext());
|
||||
return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
|
||||
D->getLocation(), Parent,
|
||||
D->getLexicalDeclContext(),
|
||||
SymbolRoleSet());
|
||||
}
|
||||
|
||||
bool VisitClassTemplateSpecializationDecl(const
|
||||
ClassTemplateSpecializationDecl *D) {
|
||||
// FIXME: Notify subsequent callbacks if info comes from implicit
|
||||
// instantiation.
|
||||
if (D->isThisDeclarationADefinition() &&
|
||||
(IndexCtx.shouldIndexImplicitTemplateInsts() ||
|
||||
!IndexCtx.isTemplateImplicitInstantiation(D)))
|
||||
if (D->isThisDeclarationADefinition())
|
||||
IndexCtx.indexTagDecl(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
|
||||
IndexCtx.handleFunctionTemplate(D);
|
||||
FunctionDecl *FD = D->getTemplatedDecl();
|
||||
handleDeclarator(FD, D);
|
||||
if (FD->isThisDeclarationADefinition()) {
|
||||
const Stmt *Body = FD->getBody();
|
||||
if (Body) {
|
||||
IndexCtx.indexBody(Body, D, FD);
|
||||
}
|
||||
bool VisitTemplateDecl(const TemplateDecl *D) {
|
||||
// FIXME: Template parameters.
|
||||
return Visit(D->getTemplatedDecl());
|
||||
}
|
||||
|
||||
bool VisitFriendDecl(const FriendDecl *D) {
|
||||
if (auto ND = D->getFriendDecl()) {
|
||||
// FIXME: Ignore a class template in a dependent context, these are not
|
||||
// linked properly with their redeclarations, ending up with duplicate
|
||||
// USRs.
|
||||
// See comment "Friend templates are visible in fairly strange ways." in
|
||||
// SemaTemplate.cpp which precedes code that prevents the friend template
|
||||
// from becoming visible from the enclosing context.
|
||||
if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
|
||||
return true;
|
||||
return Visit(ND);
|
||||
}
|
||||
if (auto Ty = D->getFriendType()) {
|
||||
IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
|
||||
IndexCtx.handleTypeAliasTemplate(D);
|
||||
IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitImportDecl(const ImportDecl *D) {
|
||||
IndexCtx.importedModule(D);
|
||||
return true;
|
||||
return IndexCtx.importedModule(D);
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void IndexingContext::indexDecl(const Decl *D) {
|
||||
bool IndexingContext::indexDecl(const Decl *D) {
|
||||
if (D->isImplicit() && shouldIgnoreIfImplicit(D))
|
||||
return;
|
||||
return true;
|
||||
|
||||
bool Handled = IndexingDeclVisitor(*this).Visit(D);
|
||||
if (!Handled && isa<DeclContext>(D))
|
||||
indexDeclContext(cast<DeclContext>(D));
|
||||
if (isTemplateImplicitInstantiation(D))
|
||||
return true;
|
||||
|
||||
IndexingDeclVisitor Visitor(*this);
|
||||
bool ShouldContinue = Visitor.Visit(D);
|
||||
if (!ShouldContinue)
|
||||
return false;
|
||||
|
||||
if (!Visitor.Handled && isa<DeclContext>(D))
|
||||
return indexDeclContext(cast<DeclContext>(D));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IndexingContext::indexDeclContext(const DeclContext *DC) {
|
||||
bool IndexingContext::indexDeclContext(const DeclContext *DC) {
|
||||
for (const auto *I : DC->decls())
|
||||
indexDecl(I);
|
||||
if (!indexDecl(I))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void IndexingContext::indexTopLevelDecl(const Decl *D) {
|
||||
if (isNotFromSourceFile(D->getLocation()))
|
||||
return;
|
||||
bool IndexingContext::indexTopLevelDecl(const Decl *D) {
|
||||
if (D->getLocation().isInvalid())
|
||||
return true;
|
||||
|
||||
if (isa<ObjCMethodDecl>(D))
|
||||
return; // Wait for the objc container.
|
||||
return true; // Wait for the objc container.
|
||||
|
||||
indexDecl(D);
|
||||
return indexDecl(D);
|
||||
}
|
||||
|
||||
void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
|
||||
bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
|
||||
for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
|
||||
indexTopLevelDecl(*I);
|
||||
if (!indexTopLevelDecl(*I))
|
||||
return false;
|
||||
return true;
|
||||
}
|
187
clang/lib/Index/IndexSymbol.cpp
Normal file
187
clang/lib/Index/IndexSymbol.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
//===--- IndexSymbol.cpp - Types and functions for indexing symbols -------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/IndexSymbol.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::index;
|
||||
|
||||
SymbolInfo index::getSymbolInfo(const Decl *D) {
|
||||
assert(D);
|
||||
SymbolInfo Info;
|
||||
Info.Kind = SymbolKind::Unknown;
|
||||
Info.TemplateKind = SymbolCXXTemplateKind::NonTemplate;
|
||||
Info.Lang = SymbolLanguage::C;
|
||||
|
||||
if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
|
||||
switch (TD->getTagKind()) {
|
||||
case TTK_Struct:
|
||||
Info.Kind = SymbolKind::Struct; break;
|
||||
case TTK_Union:
|
||||
Info.Kind = SymbolKind::Union; break;
|
||||
case TTK_Class:
|
||||
Info.Kind = SymbolKind::CXXClass;
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
break;
|
||||
case TTK_Interface:
|
||||
Info.Kind = SymbolKind::CXXInterface;
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
break;
|
||||
case TTK_Enum:
|
||||
Info.Kind = SymbolKind::Enum; break;
|
||||
}
|
||||
|
||||
if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D))
|
||||
if (!CXXRec->isCLike())
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
|
||||
if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
|
||||
Info.TemplateKind = SymbolCXXTemplateKind::TemplatePartialSpecialization;
|
||||
} else if (isa<ClassTemplateSpecializationDecl>(D)) {
|
||||
Info.TemplateKind = SymbolCXXTemplateKind::TemplateSpecialization;
|
||||
}
|
||||
|
||||
} else {
|
||||
switch (D->getKind()) {
|
||||
case Decl::Typedef:
|
||||
Info.Kind = SymbolKind::Typedef; break;
|
||||
case Decl::Function:
|
||||
Info.Kind = SymbolKind::Function;
|
||||
break;
|
||||
case Decl::ParmVar:
|
||||
Info.Kind = SymbolKind::Variable;
|
||||
break;
|
||||
case Decl::Var:
|
||||
Info.Kind = SymbolKind::Variable;
|
||||
if (isa<CXXRecordDecl>(D->getDeclContext())) {
|
||||
Info.Kind = SymbolKind::CXXStaticVariable;
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
}
|
||||
break;
|
||||
case Decl::Field:
|
||||
Info.Kind = SymbolKind::Field;
|
||||
if (const CXXRecordDecl *
|
||||
CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
|
||||
if (!CXXRec->isCLike())
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
}
|
||||
break;
|
||||
case Decl::EnumConstant:
|
||||
Info.Kind = SymbolKind::EnumConstant; break;
|
||||
case Decl::ObjCInterface:
|
||||
case Decl::ObjCImplementation:
|
||||
Info.Kind = SymbolKind::ObjCClass;
|
||||
Info.Lang = SymbolLanguage::ObjC;
|
||||
break;
|
||||
case Decl::ObjCProtocol:
|
||||
Info.Kind = SymbolKind::ObjCProtocol;
|
||||
Info.Lang = SymbolLanguage::ObjC;
|
||||
break;
|
||||
case Decl::ObjCCategory:
|
||||
case Decl::ObjCCategoryImpl:
|
||||
Info.Kind = SymbolKind::ObjCCategory;
|
||||
Info.Lang = SymbolLanguage::ObjC;
|
||||
break;
|
||||
case Decl::ObjCMethod:
|
||||
if (cast<ObjCMethodDecl>(D)->isInstanceMethod())
|
||||
Info.Kind = SymbolKind::ObjCInstanceMethod;
|
||||
else
|
||||
Info.Kind = SymbolKind::ObjCClassMethod;
|
||||
Info.Lang = SymbolLanguage::ObjC;
|
||||
break;
|
||||
case Decl::ObjCProperty:
|
||||
Info.Kind = SymbolKind::ObjCProperty;
|
||||
Info.Lang = SymbolLanguage::ObjC;
|
||||
break;
|
||||
case Decl::ObjCIvar:
|
||||
Info.Kind = SymbolKind::ObjCIvar;
|
||||
Info.Lang = SymbolLanguage::ObjC;
|
||||
break;
|
||||
case Decl::Namespace:
|
||||
Info.Kind = SymbolKind::CXXNamespace;
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
break;
|
||||
case Decl::NamespaceAlias:
|
||||
Info.Kind = SymbolKind::CXXNamespaceAlias;
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
break;
|
||||
case Decl::CXXConstructor:
|
||||
Info.Kind = SymbolKind::CXXConstructor;
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
break;
|
||||
case Decl::CXXDestructor:
|
||||
Info.Kind = SymbolKind::CXXDestructor;
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
break;
|
||||
case Decl::CXXConversion:
|
||||
Info.Kind = SymbolKind::CXXConversionFunction;
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
break;
|
||||
case Decl::CXXMethod: {
|
||||
const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
|
||||
if (MD->isStatic())
|
||||
Info.Kind = SymbolKind::CXXStaticMethod;
|
||||
else
|
||||
Info.Kind = SymbolKind::CXXInstanceMethod;
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
break;
|
||||
}
|
||||
case Decl::ClassTemplate:
|
||||
Info.Kind = SymbolKind::CXXClass;
|
||||
Info.TemplateKind = SymbolCXXTemplateKind::Template;
|
||||
break;
|
||||
case Decl::FunctionTemplate:
|
||||
Info.Kind = SymbolKind::Function;
|
||||
Info.TemplateKind = SymbolCXXTemplateKind::Template;
|
||||
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
|
||||
cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
|
||||
if (isa<CXXConstructorDecl>(MD))
|
||||
Info.Kind = SymbolKind::CXXConstructor;
|
||||
else if (isa<CXXDestructorDecl>(MD))
|
||||
Info.Kind = SymbolKind::CXXDestructor;
|
||||
else if (isa<CXXConversionDecl>(MD))
|
||||
Info.Kind = SymbolKind::CXXConversionFunction;
|
||||
else {
|
||||
if (MD->isStatic())
|
||||
Info.Kind = SymbolKind::CXXStaticMethod;
|
||||
else
|
||||
Info.Kind = SymbolKind::CXXInstanceMethod;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Decl::TypeAliasTemplate:
|
||||
Info.Kind = SymbolKind::CXXTypeAlias;
|
||||
Info.TemplateKind = SymbolCXXTemplateKind::Template;
|
||||
break;
|
||||
case Decl::TypeAlias:
|
||||
Info.Kind = SymbolKind::CXXTypeAlias;
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Info.Kind == SymbolKind::Unknown)
|
||||
return Info;
|
||||
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
if (FD->getTemplatedKind() ==
|
||||
FunctionDecl::TK_FunctionTemplateSpecialization)
|
||||
Info.TemplateKind = SymbolCXXTemplateKind::TemplateSpecialization;
|
||||
}
|
||||
|
||||
if (Info.TemplateKind != SymbolCXXTemplateKind::NonTemplate)
|
||||
Info.Lang = SymbolLanguage::CXX;
|
||||
|
||||
return Info;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
|
||||
//===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -11,7 +11,7 @@
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace cxindex;
|
||||
using namespace index;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -19,20 +19,58 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
|
||||
IndexingContext &IndexCtx;
|
||||
const NamedDecl *Parent;
|
||||
const DeclContext *ParentDC;
|
||||
bool IsBase;
|
||||
SmallVector<SymbolRelation, 3> Relations;
|
||||
|
||||
typedef RecursiveASTVisitor<TypeIndexer> base;
|
||||
|
||||
public:
|
||||
TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
|
||||
const DeclContext *DC)
|
||||
: IndexCtx(indexCtx), Parent(parent), ParentDC(DC) { }
|
||||
const DeclContext *DC, bool isBase)
|
||||
: IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
|
||||
if (IsBase) {
|
||||
assert(Parent);
|
||||
Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
|
||||
}
|
||||
}
|
||||
|
||||
bool shouldWalkTypesOfTypeLocs() const { return false; }
|
||||
|
||||
bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
|
||||
IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
|
||||
Parent, ParentDC);
|
||||
return IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
|
||||
Parent, ParentDC, SymbolRoleSet(),
|
||||
Relations);
|
||||
}
|
||||
|
||||
#define TRY_TO(CALL_EXPR) \
|
||||
do { \
|
||||
if (!CALL_EXPR) \
|
||||
return false; \
|
||||
} while (0)
|
||||
|
||||
bool traverseParamVarHelper(ParmVarDecl *D) {
|
||||
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
|
||||
if (D->getTypeSourceInfo())
|
||||
TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraverseParmVarDecl(ParmVarDecl *D) {
|
||||
// Avoid visiting default arguments from the definition that were already
|
||||
// visited in the declaration.
|
||||
// FIXME: A free function definition can have default arguments.
|
||||
// Avoiding double visitaiton of default arguments should be handled by the
|
||||
// visitor probably with a bit in the AST to indicate if the attached
|
||||
// default argument was 'inherited' or written in source.
|
||||
if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
|
||||
if (FD->isThisDeclarationADefinition()) {
|
||||
return traverseParamVarHelper(D);
|
||||
}
|
||||
}
|
||||
|
||||
return base::TraverseParmVarDecl(D);
|
||||
}
|
||||
|
||||
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
|
||||
IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
|
||||
return true;
|
||||
@ -48,24 +86,20 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (D->getLocation() == TL.getNameLoc())
|
||||
IndexCtx.handleTagDecl(D);
|
||||
else
|
||||
IndexCtx.handleReference(D, TL.getNameLoc(),
|
||||
Parent, ParentDC);
|
||||
return true;
|
||||
return IndexCtx.handleReference(D, TL.getNameLoc(),
|
||||
Parent, ParentDC, SymbolRoleSet(),
|
||||
Relations);
|
||||
}
|
||||
|
||||
bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
|
||||
IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
|
||||
Parent, ParentDC);
|
||||
return true;
|
||||
return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
|
||||
Parent, ParentDC, SymbolRoleSet());
|
||||
}
|
||||
|
||||
bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
|
||||
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
|
||||
IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
|
||||
Parent, ParentDC);
|
||||
Parent, ParentDC, SymbolRoleSet());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -75,11 +109,11 @@ public:
|
||||
if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
|
||||
if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
|
||||
IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
|
||||
Parent, ParentDC);
|
||||
Parent, ParentDC, SymbolRoleSet(), Relations);
|
||||
} else {
|
||||
if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
|
||||
IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
|
||||
Parent, ParentDC);
|
||||
Parent, ParentDC, SymbolRoleSet(), Relations);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -95,22 +129,24 @@ public:
|
||||
|
||||
void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
|
||||
const NamedDecl *Parent,
|
||||
const DeclContext *DC) {
|
||||
const DeclContext *DC,
|
||||
bool isBase) {
|
||||
if (!TInfo || TInfo->getTypeLoc().isNull())
|
||||
return;
|
||||
|
||||
indexTypeLoc(TInfo->getTypeLoc(), Parent, DC);
|
||||
indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase);
|
||||
}
|
||||
|
||||
void IndexingContext::indexTypeLoc(TypeLoc TL,
|
||||
const NamedDecl *Parent,
|
||||
const DeclContext *DC) {
|
||||
const DeclContext *DC,
|
||||
bool isBase) {
|
||||
if (TL.isNull())
|
||||
return;
|
||||
|
||||
if (!DC)
|
||||
DC = Parent->getLexicalDeclContext();
|
||||
TypeIndexer(*this, Parent, DC).TraverseTypeLoc(TL);
|
||||
TypeIndexer(*this, Parent, DC, isBase).TraverseTypeLoc(TL);
|
||||
}
|
||||
|
||||
void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
|
||||
@ -134,11 +170,11 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
|
||||
|
||||
case NestedNameSpecifier::Namespace:
|
||||
handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
|
||||
Loc, Parent, DC);
|
||||
Loc, Parent, DC, SymbolRoleSet());
|
||||
break;
|
||||
case NestedNameSpecifier::NamespaceAlias:
|
||||
handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
|
||||
Loc, Parent, DC);
|
||||
Loc, Parent, DC, SymbolRoleSet());
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
@ -149,8 +185,18 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
|
||||
}
|
||||
|
||||
void IndexingContext::indexTagDecl(const TagDecl *D) {
|
||||
if (handleTagDecl(D)) {
|
||||
if (D->isThisDeclarationADefinition())
|
||||
if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
|
||||
return;
|
||||
|
||||
if (handleDecl(D)) {
|
||||
if (D->isThisDeclarationADefinition()) {
|
||||
indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
|
||||
if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
|
||||
for (const auto &I : CXXRD->bases()) {
|
||||
indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
|
||||
}
|
||||
}
|
||||
indexDeclContext(D);
|
||||
}
|
||||
}
|
||||
}
|
140
clang/lib/Index/IndexingAction.cpp
Normal file
140
clang/lib/Index/IndexingAction.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
//===- IndexingAction.cpp - Frontend index action -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/IndexingAction.h"
|
||||
#include "clang/Index/IndexDataConsumer.h"
|
||||
#include "IndexingContext.h"
|
||||
#include "clang/Frontend/FrontendAction.h"
|
||||
#include "clang/Frontend/MultiplexConsumer.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::index;
|
||||
|
||||
void IndexDataConsumer::_anchor() {}
|
||||
|
||||
bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
|
||||
ArrayRef<SymbolRelation> Relations,
|
||||
FileID FID, unsigned Offset,
|
||||
ASTNodeInfo ASTNode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
|
||||
const MacroInfo *MI, SymbolRoleSet Roles,
|
||||
FileID FID, unsigned Offset) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
|
||||
SymbolRoleSet Roles,
|
||||
FileID FID, unsigned Offset) {
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class IndexASTConsumer : public ASTConsumer {
|
||||
IndexingContext &IndexCtx;
|
||||
|
||||
public:
|
||||
IndexASTConsumer(IndexingContext &IndexCtx)
|
||||
: IndexCtx(IndexCtx) {}
|
||||
|
||||
protected:
|
||||
void Initialize(ASTContext &Context) override {
|
||||
IndexCtx.setASTContext(Context);
|
||||
}
|
||||
|
||||
bool HandleTopLevelDecl(DeclGroupRef DG) override {
|
||||
return IndexCtx.indexDeclGroupRef(DG);
|
||||
}
|
||||
|
||||
void HandleInterestingDecl(DeclGroupRef DG) override {
|
||||
// Ignore deserialized decls.
|
||||
}
|
||||
|
||||
void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
|
||||
IndexCtx.indexDeclGroupRef(DG);
|
||||
}
|
||||
|
||||
void HandleTranslationUnit(ASTContext &Ctx) override {
|
||||
}
|
||||
};
|
||||
|
||||
class IndexAction : public WrapperFrontendAction {
|
||||
IndexingOptions IndexOpts;
|
||||
std::shared_ptr<IndexDataConsumer> DataConsumer;
|
||||
std::unique_ptr<IndexingContext> IndexCtx;
|
||||
|
||||
public:
|
||||
IndexAction(std::unique_ptr<FrontendAction> WrappedAction,
|
||||
std::shared_ptr<IndexDataConsumer> DataConsumer,
|
||||
IndexingOptions Opts)
|
||||
: WrapperFrontendAction(std::move(WrappedAction)),
|
||||
IndexOpts(Opts),
|
||||
DataConsumer(std::move(DataConsumer)) {}
|
||||
|
||||
protected:
|
||||
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
||||
StringRef InFile) override;
|
||||
void EndSourceFileAction() override;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void IndexAction::EndSourceFileAction() {
|
||||
// Invoke wrapped action's method.
|
||||
WrapperFrontendAction::EndSourceFileAction();
|
||||
|
||||
bool IndexActionFailed = !IndexCtx;
|
||||
if (!IndexActionFailed)
|
||||
DataConsumer->finish();
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTConsumer>
|
||||
IndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
|
||||
auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
|
||||
if (!OtherConsumer)
|
||||
return nullptr;
|
||||
|
||||
IndexCtx.reset(new IndexingContext(IndexOpts, *DataConsumer));
|
||||
|
||||
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
|
||||
Consumers.push_back(std::move(OtherConsumer));
|
||||
Consumers.push_back(llvm::make_unique<IndexASTConsumer>(*IndexCtx));
|
||||
return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
|
||||
}
|
||||
|
||||
std::unique_ptr<FrontendAction>
|
||||
index::createIndexingAction(std::unique_ptr<FrontendAction> WrappedAction,
|
||||
std::shared_ptr<IndexDataConsumer> DataConsumer,
|
||||
IndexingOptions Opts) {
|
||||
return llvm::make_unique<IndexAction>(std::move(WrappedAction),
|
||||
std::move(DataConsumer),
|
||||
Opts);
|
||||
}
|
||||
|
||||
|
||||
static bool topLevelDeclVisitor(void *context, const Decl *D) {
|
||||
IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
|
||||
return IndexCtx.indexTopLevelDecl(D);
|
||||
}
|
||||
|
||||
static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
|
||||
Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
|
||||
}
|
||||
|
||||
void index::indexASTUnit(ASTUnit &Unit,
|
||||
std::shared_ptr<IndexDataConsumer> DataConsumer,
|
||||
IndexingOptions Opts) {
|
||||
IndexingContext IndexCtx(Opts, *DataConsumer);
|
||||
IndexCtx.setASTContext(Unit.getASTContext());
|
||||
indexTranslationUnit(Unit, IndexCtx);
|
||||
}
|
325
clang/lib/Index/IndexingContext.cpp
Normal file
325
clang/lib/Index/IndexingContext.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
//===- IndexingContext.cpp - Indexing context data ------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IndexingContext.h"
|
||||
#include "clang/Index/IndexDataConsumer.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace index;
|
||||
|
||||
bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
|
||||
return IndexOpts.IndexFunctionLocals;
|
||||
}
|
||||
|
||||
bool IndexingContext::handleDecl(const Decl *D,
|
||||
SymbolRoleSet Roles,
|
||||
ArrayRef<SymbolRelation> Relations) {
|
||||
return handleDeclOccurrence(D, D->getLocation(), /*IsRef=*/false,
|
||||
cast<Decl>(D->getDeclContext()), Roles, Relations,
|
||||
nullptr, nullptr, D->getDeclContext());
|
||||
}
|
||||
|
||||
bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
|
||||
SymbolRoleSet Roles,
|
||||
ArrayRef<SymbolRelation> Relations,
|
||||
const DeclContext *DC) {
|
||||
if (!DC)
|
||||
DC = D->getDeclContext();
|
||||
return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
|
||||
Roles, Relations,
|
||||
nullptr, nullptr, DC);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
|
||||
const NamedDecl *Parent,
|
||||
const DeclContext *DC,
|
||||
SymbolRoleSet Roles,
|
||||
ArrayRef<SymbolRelation> Relations,
|
||||
const Expr *RefE,
|
||||
const Decl *RefD) {
|
||||
if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
|
||||
return true;
|
||||
|
||||
if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
|
||||
return true;
|
||||
|
||||
return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
|
||||
RefE, RefD, DC);
|
||||
}
|
||||
|
||||
bool IndexingContext::importedModule(const ImportDecl *ImportD) {
|
||||
SourceLocation Loc = ImportD->getLocation();
|
||||
SourceManager &SM = Ctx->getSourceManager();
|
||||
Loc = SM.getFileLoc(Loc);
|
||||
if (Loc.isInvalid())
|
||||
return true;
|
||||
|
||||
FileID FID;
|
||||
unsigned Offset;
|
||||
std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
|
||||
if (FID.isInvalid())
|
||||
return true;
|
||||
|
||||
bool Invalid = false;
|
||||
const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
|
||||
if (Invalid || !SEntry.isFile())
|
||||
return true;
|
||||
|
||||
if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
|
||||
switch (IndexOpts.SystemSymbolFilter) {
|
||||
case IndexingOptions::SystemSymbolFilterKind::None:
|
||||
case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
|
||||
return true;
|
||||
case IndexingOptions::SystemSymbolFilterKind::All:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SymbolRoleSet Roles{};
|
||||
if (ImportD->isImplicit())
|
||||
Roles |= (unsigned)SymbolRole::Implicit;
|
||||
|
||||
return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
|
||||
}
|
||||
|
||||
bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
|
||||
assert(D);
|
||||
|
||||
if (isa<TemplateTemplateParmDecl>(D))
|
||||
return true;
|
||||
|
||||
if (!D->getParentFunctionOrMethod())
|
||||
return false;
|
||||
|
||||
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
|
||||
switch (ND->getFormalLinkage()) {
|
||||
case NoLinkage:
|
||||
case VisibleNoLinkage:
|
||||
case InternalLinkage:
|
||||
return true;
|
||||
case UniqueExternalLinkage:
|
||||
llvm_unreachable("Not a sema linkage");
|
||||
case ExternalLinkage:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
|
||||
TemplateSpecializationKind TKind = TSK_Undeclared;
|
||||
if (const ClassTemplateSpecializationDecl *
|
||||
SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
|
||||
TKind = SD->getSpecializationKind();
|
||||
}
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
TKind = FD->getTemplateSpecializationKind();
|
||||
}
|
||||
switch (TKind) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
return false;
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
|
||||
if (isa<ObjCInterfaceDecl>(D))
|
||||
return false;
|
||||
if (isa<ObjCCategoryDecl>(D))
|
||||
return false;
|
||||
if (isa<ObjCIvarDecl>(D))
|
||||
return false;
|
||||
if (isa<ObjCMethodDecl>(D))
|
||||
return false;
|
||||
if (isa<ImportDecl>(D))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
|
||||
if (const ClassTemplateSpecializationDecl *
|
||||
SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
|
||||
return SD->getTemplateInstantiationPattern();
|
||||
}
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
return FD->getTemplateInstantiationPattern();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool isDeclADefinition(const Decl *D, ASTContext &Ctx) {
|
||||
if (auto VD = dyn_cast<VarDecl>(D))
|
||||
return VD->isThisDeclarationADefinition(Ctx);
|
||||
|
||||
if (auto FD = dyn_cast<FunctionDecl>(D))
|
||||
return FD->isThisDeclarationADefinition();
|
||||
|
||||
if (auto TD = dyn_cast<TagDecl>(D))
|
||||
return TD->isThisDeclarationADefinition();
|
||||
|
||||
if (auto MD = dyn_cast<ObjCMethodDecl>(D))
|
||||
return MD->isThisDeclarationADefinition();
|
||||
|
||||
if (isa<TypedefNameDecl>(D) ||
|
||||
isa<EnumConstantDecl>(D) ||
|
||||
isa<FieldDecl>(D) ||
|
||||
isa<MSPropertyDecl>(D) ||
|
||||
isa<ObjCImplDecl>(D) ||
|
||||
isa<ObjCPropertyImplDecl>(D))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const Decl *adjustParent(const Decl *Parent) {
|
||||
if (!Parent)
|
||||
return nullptr;
|
||||
for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
|
||||
if (isa<TranslationUnitDecl>(Parent))
|
||||
return nullptr;
|
||||
if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
|
||||
continue;
|
||||
if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
|
||||
if (NS->isAnonymousNamespace())
|
||||
continue;
|
||||
} else if (auto EnumD = dyn_cast<EnumDecl>(Parent)) {
|
||||
// Move enumerators under anonymous enum to the enclosing parent.
|
||||
if (EnumD->getDeclName().isEmpty())
|
||||
continue;
|
||||
} else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
|
||||
if (RD->isAnonymousStructOrUnion())
|
||||
continue;
|
||||
} else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
|
||||
if (FD->getDeclName().isEmpty())
|
||||
continue;
|
||||
}
|
||||
return Parent;
|
||||
}
|
||||
}
|
||||
|
||||
static const Decl *getCanonicalDecl(const Decl *D) {
|
||||
D = D->getCanonicalDecl();
|
||||
if (auto TD = dyn_cast<TemplateDecl>(D)) {
|
||||
D = TD->getTemplatedDecl();
|
||||
assert(D->isCanonicalDecl());
|
||||
}
|
||||
|
||||
return D;
|
||||
}
|
||||
|
||||
bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
|
||||
bool IsRef, const Decl *Parent,
|
||||
SymbolRoleSet Roles,
|
||||
ArrayRef<SymbolRelation> Relations,
|
||||
const Expr *OrigE,
|
||||
const Decl *OrigD,
|
||||
const DeclContext *ContainerDC) {
|
||||
if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
|
||||
return true;
|
||||
if (!isa<NamedDecl>(D) ||
|
||||
(cast<NamedDecl>(D)->getDeclName().isEmpty() &&
|
||||
!isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
|
||||
return true;
|
||||
|
||||
SourceManager &SM = Ctx->getSourceManager();
|
||||
Loc = SM.getFileLoc(Loc);
|
||||
if (Loc.isInvalid())
|
||||
return true;
|
||||
|
||||
FileID FID;
|
||||
unsigned Offset;
|
||||
std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
|
||||
if (FID.isInvalid())
|
||||
return true;
|
||||
|
||||
bool Invalid = false;
|
||||
const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
|
||||
if (Invalid || !SEntry.isFile())
|
||||
return true;
|
||||
|
||||
if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
|
||||
switch (IndexOpts.SystemSymbolFilter) {
|
||||
case IndexingOptions::SystemSymbolFilterKind::None:
|
||||
return true;
|
||||
case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
|
||||
if (IsRef)
|
||||
return true;
|
||||
break;
|
||||
case IndexingOptions::SystemSymbolFilterKind::All:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isTemplateImplicitInstantiation(D)) {
|
||||
if (!IsRef)
|
||||
return true;
|
||||
D = adjustTemplateImplicitInstantiation(D);
|
||||
if (!D)
|
||||
return true;
|
||||
assert(!isTemplateImplicitInstantiation(D));
|
||||
}
|
||||
|
||||
if (!OrigD)
|
||||
OrigD = D;
|
||||
|
||||
if (IsRef)
|
||||
Roles |= (unsigned)SymbolRole::Reference;
|
||||
else if (isDeclADefinition(D, *Ctx))
|
||||
Roles |= (unsigned)SymbolRole::Definition;
|
||||
else
|
||||
Roles |= (unsigned)SymbolRole::Declaration;
|
||||
|
||||
D = getCanonicalDecl(D);
|
||||
if (D->isImplicit() && !isa<ObjCMethodDecl>(D)) {
|
||||
// operator new declarations will link to the implicit one as canonical.
|
||||
return true;
|
||||
}
|
||||
Parent = adjustParent(Parent);
|
||||
if (Parent)
|
||||
Parent = getCanonicalDecl(Parent);
|
||||
assert(!Parent || !Parent->isImplicit() ||
|
||||
isa<ObjCInterfaceDecl>(Parent) || isa<ObjCMethodDecl>(Parent));
|
||||
|
||||
SmallVector<SymbolRelation, 6> FinalRelations;
|
||||
FinalRelations.reserve(Relations.size()+1);
|
||||
|
||||
auto addRelation = [&](SymbolRelation Rel) {
|
||||
auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
|
||||
[&](SymbolRelation Elem)->bool {
|
||||
return Elem.RelatedSymbol == Rel.RelatedSymbol;
|
||||
});
|
||||
if (It != FinalRelations.end()) {
|
||||
It->Roles |= Rel.Roles;
|
||||
} else {
|
||||
FinalRelations.push_back(Rel);
|
||||
}
|
||||
Roles |= Rel.Roles;
|
||||
};
|
||||
|
||||
if (!IsRef && Parent && !cast<DeclContext>(Parent)->isFunctionOrMethod()) {
|
||||
addRelation(SymbolRelation{(unsigned)SymbolRole::RelationChildOf, Parent});
|
||||
}
|
||||
for (auto &Rel : Relations) {
|
||||
addRelation(SymbolRelation(Rel.Roles,
|
||||
Rel.RelatedSymbol->getCanonicalDecl()));
|
||||
}
|
||||
|
||||
IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
|
||||
return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,
|
||||
Node);
|
||||
}
|
121
clang/lib/Index/IndexingContext.h
Normal file
121
clang/lib/Index/IndexingContext.h
Normal file
@ -0,0 +1,121 @@
|
||||
//===- IndexingContext.h - Indexing context data ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H
|
||||
#define LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Index/IndexSymbol.h"
|
||||
#include "clang/Index/IndexingAction.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class Decl;
|
||||
class DeclGroupRef;
|
||||
class ImportDecl;
|
||||
class TagDecl;
|
||||
class TypeSourceInfo;
|
||||
class NamedDecl;
|
||||
class ObjCMethodDecl;
|
||||
class DeclContext;
|
||||
class NestedNameSpecifierLoc;
|
||||
class Stmt;
|
||||
class Expr;
|
||||
class TypeLoc;
|
||||
class SourceLocation;
|
||||
|
||||
namespace index {
|
||||
class IndexDataConsumer;
|
||||
|
||||
class IndexingContext {
|
||||
IndexingOptions IndexOpts;
|
||||
IndexDataConsumer &DataConsumer;
|
||||
ASTContext *Ctx = nullptr;
|
||||
|
||||
public:
|
||||
IndexingContext(IndexingOptions IndexOpts, IndexDataConsumer &DataConsumer)
|
||||
: IndexOpts(IndexOpts), DataConsumer(DataConsumer) {}
|
||||
|
||||
const IndexingOptions &getIndexOpts() const { return IndexOpts; }
|
||||
IndexDataConsumer &getDataConsumer() { return DataConsumer; }
|
||||
|
||||
void setASTContext(ASTContext &ctx) { Ctx = &ctx; }
|
||||
|
||||
bool shouldSuppressRefs() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool shouldIndexFunctionLocalSymbols() const;
|
||||
|
||||
bool shouldIndexImplicitTemplateInsts() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isFunctionLocalDecl(const Decl *D);
|
||||
static bool isTemplateImplicitInstantiation(const Decl *D);
|
||||
|
||||
bool handleDecl(const Decl *D, SymbolRoleSet Roles = SymbolRoleSet(),
|
||||
ArrayRef<SymbolRelation> Relations = {});
|
||||
|
||||
bool handleDecl(const Decl *D, SourceLocation Loc,
|
||||
SymbolRoleSet Roles = SymbolRoleSet(),
|
||||
ArrayRef<SymbolRelation> Relations = {},
|
||||
const DeclContext *DC = nullptr);
|
||||
|
||||
bool handleReference(const NamedDecl *D, SourceLocation Loc,
|
||||
const NamedDecl *Parent,
|
||||
const DeclContext *DC,
|
||||
SymbolRoleSet Roles,
|
||||
ArrayRef<SymbolRelation> Relations = {},
|
||||
const Expr *RefE = nullptr,
|
||||
const Decl *RefD = nullptr);
|
||||
|
||||
bool importedModule(const ImportDecl *ImportD);
|
||||
|
||||
bool indexDecl(const Decl *D);
|
||||
|
||||
void indexTagDecl(const TagDecl *D);
|
||||
|
||||
void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
|
||||
const DeclContext *DC = nullptr,
|
||||
bool isBase = false);
|
||||
|
||||
void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
|
||||
const DeclContext *DC = nullptr,
|
||||
bool isBase = false);
|
||||
|
||||
void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
|
||||
const NamedDecl *Parent,
|
||||
const DeclContext *DC = nullptr);
|
||||
|
||||
bool indexDeclContext(const DeclContext *DC);
|
||||
|
||||
void indexBody(const Stmt *S, const NamedDecl *Parent,
|
||||
const DeclContext *DC = nullptr);
|
||||
|
||||
bool indexTopLevelDecl(const Decl *D);
|
||||
bool indexDeclGroupRef(DeclGroupRef DG);
|
||||
|
||||
private:
|
||||
bool shouldIgnoreIfImplicit(const Decl *D);
|
||||
|
||||
bool handleDeclOccurrence(const Decl *D, SourceLocation Loc,
|
||||
bool IsRef, const Decl *Parent,
|
||||
SymbolRoleSet Roles,
|
||||
ArrayRef<SymbolRelation> Relations,
|
||||
const Expr *RefE,
|
||||
const Decl *RefD,
|
||||
const DeclContext *ContainerDC);
|
||||
};
|
||||
|
||||
} // end namespace index
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
@ -11,17 +11,14 @@ set(SOURCES
|
||||
CIndexer.cpp
|
||||
CXComment.cpp
|
||||
CXCursor.cpp
|
||||
CXIndexDataConsumer.cpp
|
||||
CXCompilationDatabase.cpp
|
||||
CXLoadedDiagnostic.cpp
|
||||
CXSourceLocation.cpp
|
||||
CXStoredDiagnostic.cpp
|
||||
CXString.cpp
|
||||
CXType.cpp
|
||||
IndexBody.cpp
|
||||
IndexDecl.cpp
|
||||
IndexTypeSourceInfo.cpp
|
||||
Indexing.cpp
|
||||
IndexingContext.cpp
|
||||
|
||||
ADDITIONAL_HEADERS
|
||||
CIndexDiagnostic.h
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- IndexingContext.cpp - Higher level API functions -------------------===//
|
||||
//===- CXIndexDataConsumer.cpp - Index data consumer for libclang----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -7,21 +7,219 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IndexingContext.h"
|
||||
#include "CXIndexDataConsumer.h"
|
||||
#include "CIndexDiagnostic.h"
|
||||
#include "CXTranslationUnit.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
#include "clang/Frontend/ASTUnit.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::index;
|
||||
using namespace cxindex;
|
||||
using namespace cxcursor;
|
||||
|
||||
IndexingContext::ObjCProtocolListInfo::ObjCProtocolListInfo(
|
||||
namespace {
|
||||
class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
|
||||
CXIndexDataConsumer &DataConsumer;
|
||||
SourceLocation DeclLoc;
|
||||
const DeclContext *LexicalDC;
|
||||
|
||||
public:
|
||||
IndexingDeclVisitor(CXIndexDataConsumer &dataConsumer, SourceLocation Loc,
|
||||
const DeclContext *lexicalDC)
|
||||
: DataConsumer(dataConsumer), DeclLoc(Loc), LexicalDC(lexicalDC) { }
|
||||
|
||||
bool VisitFunctionDecl(const FunctionDecl *D) {
|
||||
DataConsumer.handleFunction(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitVarDecl(const VarDecl *D) {
|
||||
DataConsumer.handleVar(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitFieldDecl(const FieldDecl *D) {
|
||||
DataConsumer.handleField(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
|
||||
DataConsumer.handleEnumerator(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
|
||||
DataConsumer.handleTypedefName(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitTagDecl(const TagDecl *D) {
|
||||
DataConsumer.handleTagDecl(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
|
||||
DataConsumer.handleObjCInterface(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
|
||||
DataConsumer.handleObjCProtocol(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
|
||||
DataConsumer.handleObjCImplementation(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
|
||||
DataConsumer.handleObjCCategory(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
|
||||
DataConsumer.handleObjCCategoryImpl(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
|
||||
if (D->getDeclContext() != LexicalDC)
|
||||
DataConsumer.handleSynthesizedObjCMethod(D, DeclLoc, LexicalDC);
|
||||
else
|
||||
DataConsumer.handleObjCMethod(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
|
||||
DataConsumer.handleObjCProperty(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
|
||||
DataConsumer.handleSynthesizedObjCProperty(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitNamespaceDecl(const NamespaceDecl *D) {
|
||||
DataConsumer.handleNamespace(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitUsingDecl(const UsingDecl *D) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitClassTemplateDecl(const ClassTemplateDecl *D) {
|
||||
DataConsumer.handleClassTemplate(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitClassTemplateSpecializationDecl(const
|
||||
ClassTemplateSpecializationDecl *D) {
|
||||
DataConsumer.handleTagDecl(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
|
||||
DataConsumer.handleFunctionTemplate(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
|
||||
DataConsumer.handleTypeAliasTemplate(D);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitImportDecl(const ImportDecl *D) {
|
||||
DataConsumer.importedModule(D);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool CXIndexDataConsumer::handleDeclOccurence(const Decl *D,
|
||||
SymbolRoleSet Roles,
|
||||
ArrayRef<SymbolRelation> Relations,
|
||||
FileID FID, unsigned Offset,
|
||||
ASTNodeInfo ASTNode) {
|
||||
SourceLocation Loc = getASTContext().getSourceManager()
|
||||
.getLocForStartOfFile(FID).getLocWithOffset(Offset);
|
||||
|
||||
if (Roles & (unsigned)SymbolRole::Reference) {
|
||||
const NamedDecl *ND = dyn_cast<NamedDecl>(D);
|
||||
if (!ND)
|
||||
return true;
|
||||
|
||||
if (auto *ObjCID = dyn_cast_or_null<ObjCInterfaceDecl>(ASTNode.OrigD)) {
|
||||
if (!ObjCID->isThisDeclarationADefinition() &&
|
||||
ObjCID->getLocation() == Loc) {
|
||||
// The libclang API treats this as ObjCClassRef declaration.
|
||||
IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCID);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct;
|
||||
if (Roles & (unsigned)SymbolRole::Implicit) {
|
||||
Kind = CXIdxEntityRef_Implicit;
|
||||
}
|
||||
|
||||
CXCursor Cursor;
|
||||
if (ASTNode.OrigE) {
|
||||
Cursor = cxcursor::MakeCXCursor(ASTNode.OrigE,
|
||||
cast<Decl>(ASTNode.ContainerDC),
|
||||
getCXTU());
|
||||
} else {
|
||||
const NamedDecl *CursorD = dyn_cast_or_null<NamedDecl>(ASTNode.OrigD);
|
||||
if (!CursorD)
|
||||
CursorD = ND;
|
||||
Cursor = getRefCursor(CursorD, Loc);
|
||||
}
|
||||
handleReference(ND, Loc, Cursor,
|
||||
dyn_cast_or_null<NamedDecl>(ASTNode.Parent),
|
||||
ASTNode.ContainerDC, ASTNode.OrigE, Kind);
|
||||
|
||||
} else {
|
||||
const DeclContext *DC = nullptr;
|
||||
for (const auto &SymRel : Relations) {
|
||||
if (SymRel.Roles & (unsigned)SymbolRole::RelationChildOf)
|
||||
DC = dyn_cast<DeclContext>(SymRel.RelatedSymbol);
|
||||
}
|
||||
IndexingDeclVisitor(*this, Loc, DC).Visit(ASTNode.OrigD);
|
||||
}
|
||||
|
||||
return !shouldAbort();
|
||||
}
|
||||
|
||||
bool CXIndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
|
||||
SymbolRoleSet Roles,
|
||||
FileID FID,
|
||||
unsigned Offset) {
|
||||
IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
|
||||
return !shouldAbort();
|
||||
}
|
||||
|
||||
void CXIndexDataConsumer::finish() {
|
||||
indexDiagnostics();
|
||||
}
|
||||
|
||||
|
||||
CXIndexDataConsumer::ObjCProtocolListInfo::ObjCProtocolListInfo(
|
||||
const ObjCProtocolList &ProtList,
|
||||
IndexingContext &IdxCtx,
|
||||
CXIndexDataConsumer &IdxCtx,
|
||||
ScratchAlloc &SA) {
|
||||
ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
|
||||
for (ObjCInterfaceDecl::protocol_iterator
|
||||
@ -61,7 +259,7 @@ IBOutletCollectionInfo::IBOutletCollectionInfo(
|
||||
IBCollInfo.objcClass = nullptr;
|
||||
}
|
||||
|
||||
AttrListInfo::AttrListInfo(const Decl *D, IndexingContext &IdxCtx)
|
||||
AttrListInfo::AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx)
|
||||
: SA(IdxCtx), ref_cnt(0) {
|
||||
|
||||
if (!D->hasAttrs())
|
||||
@ -114,14 +312,14 @@ AttrListInfo::AttrListInfo(const Decl *D, IndexingContext &IdxCtx)
|
||||
}
|
||||
|
||||
IntrusiveRefCntPtr<AttrListInfo>
|
||||
AttrListInfo::create(const Decl *D, IndexingContext &IdxCtx) {
|
||||
AttrListInfo::create(const Decl *D, CXIndexDataConsumer &IdxCtx) {
|
||||
ScratchAlloc SA(IdxCtx);
|
||||
AttrListInfo *attrs = SA.allocate<AttrListInfo>();
|
||||
return new (attrs) AttrListInfo(D, IdxCtx);
|
||||
}
|
||||
|
||||
IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
|
||||
IndexingContext &IdxCtx,
|
||||
CXIndexDataConsumer::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
|
||||
CXIndexDataConsumer &IdxCtx,
|
||||
ScratchAlloc &SA) {
|
||||
for (const auto &Base : D->bases()) {
|
||||
BaseEntities.push_back(EntityInfo());
|
||||
@ -155,7 +353,7 @@ IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
|
||||
CXBases.push_back(&BaseInfos[i]);
|
||||
}
|
||||
|
||||
SourceLocation IndexingContext::CXXBasesListInfo::getBaseLoc(
|
||||
SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc(
|
||||
const CXXBaseSpecifier &Base) const {
|
||||
SourceLocation Loc = Base.getSourceRange().getBegin();
|
||||
TypeLoc TL;
|
||||
@ -193,16 +391,16 @@ const char *ScratchAlloc::copyCStr(StringRef Str) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
void IndexingContext::setASTContext(ASTContext &ctx) {
|
||||
void CXIndexDataConsumer::setASTContext(ASTContext &ctx) {
|
||||
Ctx = &ctx;
|
||||
cxtu::getASTUnit(CXTU)->setASTContext(&ctx);
|
||||
}
|
||||
|
||||
void IndexingContext::setPreprocessor(Preprocessor &PP) {
|
||||
void CXIndexDataConsumer::setPreprocessor(Preprocessor &PP) {
|
||||
cxtu::getASTUnit(CXTU)->setPreprocessor(&PP);
|
||||
}
|
||||
|
||||
bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
|
||||
bool CXIndexDataConsumer::isFunctionLocalDecl(const Decl *D) {
|
||||
assert(D);
|
||||
|
||||
if (!D->getParentFunctionOrMethod())
|
||||
@ -224,13 +422,13 @@ bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexingContext::shouldAbort() {
|
||||
bool CXIndexDataConsumer::shouldAbort() {
|
||||
if (!CB.abortQuery)
|
||||
return false;
|
||||
return CB.abortQuery(ClientData, nullptr);
|
||||
}
|
||||
|
||||
void IndexingContext::enteredMainFile(const FileEntry *File) {
|
||||
void CXIndexDataConsumer::enteredMainFile(const FileEntry *File) {
|
||||
if (File && CB.enteredMainFile) {
|
||||
CXIdxClientFile idxFile =
|
||||
CB.enteredMainFile(ClientData,
|
||||
@ -240,7 +438,7 @@ void IndexingContext::enteredMainFile(const FileEntry *File) {
|
||||
}
|
||||
}
|
||||
|
||||
void IndexingContext::ppIncludedFile(SourceLocation hashLoc,
|
||||
void CXIndexDataConsumer::ppIncludedFile(SourceLocation hashLoc,
|
||||
StringRef filename,
|
||||
const FileEntry *File,
|
||||
bool isImport, bool isAngled,
|
||||
@ -258,7 +456,7 @@ void IndexingContext::ppIncludedFile(SourceLocation hashLoc,
|
||||
FileMap[File] = idxFile;
|
||||
}
|
||||
|
||||
void IndexingContext::importedModule(const ImportDecl *ImportD) {
|
||||
void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) {
|
||||
if (!CB.importedASTFile)
|
||||
return;
|
||||
|
||||
@ -277,7 +475,7 @@ void IndexingContext::importedModule(const ImportDecl *ImportD) {
|
||||
(void)astFile;
|
||||
}
|
||||
|
||||
void IndexingContext::importedPCH(const FileEntry *File) {
|
||||
void CXIndexDataConsumer::importedPCH(const FileEntry *File) {
|
||||
if (!CB.importedASTFile)
|
||||
return;
|
||||
|
||||
@ -292,21 +490,29 @@ void IndexingContext::importedPCH(const FileEntry *File) {
|
||||
(void)astFile;
|
||||
}
|
||||
|
||||
void IndexingContext::startedTranslationUnit() {
|
||||
void CXIndexDataConsumer::startedTranslationUnit() {
|
||||
CXIdxClientContainer idxCont = nullptr;
|
||||
if (CB.startedTranslationUnit)
|
||||
idxCont = CB.startedTranslationUnit(ClientData, nullptr);
|
||||
addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
|
||||
}
|
||||
|
||||
void IndexingContext::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
|
||||
void CXIndexDataConsumer::indexDiagnostics() {
|
||||
if (!hasDiagnosticCallback())
|
||||
return;
|
||||
|
||||
CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(getCXTU());
|
||||
handleDiagnosticSet(DiagSet);
|
||||
}
|
||||
|
||||
void CXIndexDataConsumer::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
|
||||
if (!CB.diagnostic)
|
||||
return;
|
||||
|
||||
CB.diagnostic(ClientData, CXDiagSet, nullptr);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleDecl(const NamedDecl *D,
|
||||
bool CXIndexDataConsumer::handleDecl(const NamedDecl *D,
|
||||
SourceLocation Loc, CXCursor Cursor,
|
||||
DeclInfo &DInfo,
|
||||
const DeclContext *LexicalDC,
|
||||
@ -365,14 +571,14 @@ bool IndexingContext::handleDecl(const NamedDecl *D,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexingContext::handleObjCContainer(const ObjCContainerDecl *D,
|
||||
bool CXIndexDataConsumer::handleObjCContainer(const ObjCContainerDecl *D,
|
||||
SourceLocation Loc, CXCursor Cursor,
|
||||
ObjCContainerDeclInfo &ContDInfo) {
|
||||
ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo;
|
||||
return handleDecl(D, Loc, Cursor, ContDInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleFunction(const FunctionDecl *D) {
|
||||
bool CXIndexDataConsumer::handleFunction(const FunctionDecl *D) {
|
||||
bool isDef = D->isThisDeclarationADefinition();
|
||||
bool isContainer = isDef;
|
||||
bool isSkipped = false;
|
||||
@ -388,31 +594,31 @@ bool IndexingContext::handleFunction(const FunctionDecl *D) {
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleVar(const VarDecl *D) {
|
||||
bool CXIndexDataConsumer::handleVar(const VarDecl *D) {
|
||||
DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
|
||||
/*isContainer=*/false);
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleField(const FieldDecl *D) {
|
||||
bool CXIndexDataConsumer::handleField(const FieldDecl *D) {
|
||||
DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
|
||||
/*isContainer=*/false);
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleMSProperty(const MSPropertyDecl *D) {
|
||||
bool CXIndexDataConsumer::handleMSProperty(const MSPropertyDecl *D) {
|
||||
DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
|
||||
/*isContainer=*/false);
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleEnumerator(const EnumConstantDecl *D) {
|
||||
bool CXIndexDataConsumer::handleEnumerator(const EnumConstantDecl *D) {
|
||||
DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
|
||||
/*isContainer=*/false);
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleTagDecl(const TagDecl *D) {
|
||||
bool CXIndexDataConsumer::handleTagDecl(const TagDecl *D) {
|
||||
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D))
|
||||
return handleCXXRecordDecl(CXXRD, D);
|
||||
|
||||
@ -421,13 +627,13 @@ bool IndexingContext::handleTagDecl(const TagDecl *D) {
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleTypedefName(const TypedefNameDecl *D) {
|
||||
bool CXIndexDataConsumer::handleTypedefName(const TypedefNameDecl *D) {
|
||||
DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true,
|
||||
/*isContainer=*/false);
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) {
|
||||
bool CXIndexDataConsumer::handleObjCInterface(const ObjCInterfaceDecl *D) {
|
||||
// For @class forward declarations, suppress them the same way as references.
|
||||
if (!D->isThisDeclarationADefinition()) {
|
||||
if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
|
||||
@ -475,7 +681,7 @@ bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) {
|
||||
return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleObjCImplementation(
|
||||
bool CXIndexDataConsumer::handleObjCImplementation(
|
||||
const ObjCImplementationDecl *D) {
|
||||
ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false,
|
||||
/*isRedeclaration=*/true,
|
||||
@ -483,7 +689,7 @@ bool IndexingContext::handleObjCImplementation(
|
||||
return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) {
|
||||
bool CXIndexDataConsumer::handleObjCProtocol(const ObjCProtocolDecl *D) {
|
||||
if (!D->isThisDeclarationADefinition()) {
|
||||
if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
|
||||
return false; // already occurred.
|
||||
@ -512,7 +718,7 @@ bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) {
|
||||
return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) {
|
||||
bool CXIndexDataConsumer::handleObjCCategory(const ObjCCategoryDecl *D) {
|
||||
ScratchAlloc SA(*this);
|
||||
|
||||
ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false);
|
||||
@ -544,7 +750,7 @@ bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) {
|
||||
return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
|
||||
bool CXIndexDataConsumer::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
|
||||
ScratchAlloc SA(*this);
|
||||
|
||||
const ObjCCategoryDecl *CatD = D->getCategoryDecl();
|
||||
@ -573,7 +779,7 @@ bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
|
||||
return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) {
|
||||
bool CXIndexDataConsumer::handleObjCMethod(const ObjCMethodDecl *D) {
|
||||
bool isDef = D->isThisDeclarationADefinition();
|
||||
bool isContainer = isDef;
|
||||
bool isSkipped = false;
|
||||
@ -589,7 +795,7 @@ bool IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) {
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleSynthesizedObjCProperty(
|
||||
bool CXIndexDataConsumer::handleSynthesizedObjCProperty(
|
||||
const ObjCPropertyImplDecl *D) {
|
||||
ObjCPropertyDecl *PD = D->getPropertyDecl();
|
||||
auto *DC = D->getDeclContext();
|
||||
@ -597,7 +803,7 @@ bool IndexingContext::handleSynthesizedObjCProperty(
|
||||
dyn_cast<NamedDecl>(DC), DC);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
|
||||
bool CXIndexDataConsumer::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
|
||||
SourceLocation Loc,
|
||||
const DeclContext *LexicalDC) {
|
||||
DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true,
|
||||
@ -605,7 +811,7 @@ bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
|
||||
return handleDecl(D, Loc, getCursor(D), DInfo, LexicalDC, LexicalDC);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) {
|
||||
bool CXIndexDataConsumer::handleObjCProperty(const ObjCPropertyDecl *D) {
|
||||
ScratchAlloc SA(*this);
|
||||
|
||||
ObjCPropertyDeclInfo DInfo;
|
||||
@ -630,31 +836,31 @@ bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) {
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleNamespace(const NamespaceDecl *D) {
|
||||
bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) {
|
||||
DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(),
|
||||
/*isDefinition=*/true,
|
||||
/*isContainer=*/true);
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleClassTemplate(const ClassTemplateDecl *D) {
|
||||
bool CXIndexDataConsumer::handleClassTemplate(const ClassTemplateDecl *D) {
|
||||
return handleCXXRecordDecl(D->getTemplatedDecl(), D);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleFunctionTemplate(const FunctionTemplateDecl *D) {
|
||||
bool CXIndexDataConsumer::handleFunctionTemplate(const FunctionTemplateDecl *D) {
|
||||
DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
|
||||
/*isDefinition=*/D->isThisDeclarationADefinition(),
|
||||
/*isContainer=*/D->isThisDeclarationADefinition());
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) {
|
||||
bool CXIndexDataConsumer::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) {
|
||||
DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
|
||||
/*isDefinition=*/true, /*isContainer=*/false);
|
||||
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
|
||||
bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc,
|
||||
const NamedDecl *Parent,
|
||||
const DeclContext *DC,
|
||||
const Expr *E,
|
||||
@ -667,7 +873,7 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
|
||||
return handleReference(D, Loc, Cursor, Parent, DC, E, Kind);
|
||||
}
|
||||
|
||||
bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
|
||||
bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc,
|
||||
CXCursor Cursor,
|
||||
const NamedDecl *Parent,
|
||||
const DeclContext *DC,
|
||||
@ -713,7 +919,7 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const {
|
||||
bool CXIndexDataConsumer::isNotFromSourceFile(SourceLocation Loc) const {
|
||||
if (Loc.isInvalid())
|
||||
return true;
|
||||
SourceManager &SM = Ctx->getSourceManager();
|
||||
@ -722,7 +928,7 @@ bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const {
|
||||
return SM.getFileEntryForID(FID) == nullptr;
|
||||
}
|
||||
|
||||
void IndexingContext::addContainerInMap(const DeclContext *DC,
|
||||
void CXIndexDataConsumer::addContainerInMap(const DeclContext *DC,
|
||||
CXIdxClientContainer container) {
|
||||
if (!DC)
|
||||
return;
|
||||
@ -741,7 +947,7 @@ void IndexingContext::addContainerInMap(const DeclContext *DC,
|
||||
ContainerMap.erase(I);
|
||||
}
|
||||
|
||||
CXIdxClientEntity IndexingContext::getClientEntity(const Decl *D) const {
|
||||
CXIdxClientEntity CXIndexDataConsumer::getClientEntity(const Decl *D) const {
|
||||
if (!D)
|
||||
return nullptr;
|
||||
EntityMapTy::const_iterator I = EntityMap.find(D);
|
||||
@ -750,13 +956,13 @@ CXIdxClientEntity IndexingContext::getClientEntity(const Decl *D) const {
|
||||
return I->second;
|
||||
}
|
||||
|
||||
void IndexingContext::setClientEntity(const Decl *D, CXIdxClientEntity client) {
|
||||
void CXIndexDataConsumer::setClientEntity(const Decl *D, CXIdxClientEntity client) {
|
||||
if (!D)
|
||||
return;
|
||||
EntityMap[D] = client;
|
||||
}
|
||||
|
||||
bool IndexingContext::handleCXXRecordDecl(const CXXRecordDecl *RD,
|
||||
bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD,
|
||||
const NamedDecl *OrigD) {
|
||||
if (RD->isThisDeclarationADefinition()) {
|
||||
ScratchAlloc SA(*this);
|
||||
@ -789,7 +995,7 @@ bool IndexingContext::handleCXXRecordDecl(const CXXRecordDecl *RD,
|
||||
return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo);
|
||||
}
|
||||
|
||||
bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D,
|
||||
bool CXIndexDataConsumer::markEntityOccurrenceInFile(const NamedDecl *D,
|
||||
SourceLocation Loc) {
|
||||
if (!D || Loc.isInvalid())
|
||||
return true;
|
||||
@ -811,7 +1017,7 @@ bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D,
|
||||
return !res.second; // already in map
|
||||
}
|
||||
|
||||
const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const {
|
||||
const NamedDecl *CXIndexDataConsumer::getEntityDecl(const NamedDecl *D) const {
|
||||
assert(D);
|
||||
D = cast<NamedDecl>(D->getCanonicalDecl());
|
||||
|
||||
@ -834,7 +1040,7 @@ const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const {
|
||||
}
|
||||
|
||||
const DeclContext *
|
||||
IndexingContext::getEntityContainer(const Decl *D) const {
|
||||
CXIndexDataConsumer::getEntityContainer(const Decl *D) const {
|
||||
const DeclContext *DC = dyn_cast<DeclContext>(D);
|
||||
if (DC)
|
||||
return DC;
|
||||
@ -850,7 +1056,7 @@ IndexingContext::getEntityContainer(const Decl *D) const {
|
||||
}
|
||||
|
||||
CXIdxClientContainer
|
||||
IndexingContext::getClientContainerForDC(const DeclContext *DC) const {
|
||||
CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DC) const {
|
||||
if (!DC)
|
||||
return nullptr;
|
||||
|
||||
@ -861,7 +1067,7 @@ IndexingContext::getClientContainerForDC(const DeclContext *DC) const {
|
||||
return I->second;
|
||||
}
|
||||
|
||||
CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) {
|
||||
CXIdxClientFile CXIndexDataConsumer::getIndexFile(const FileEntry *File) {
|
||||
if (!File)
|
||||
return nullptr;
|
||||
|
||||
@ -872,17 +1078,17 @@ CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CXIdxLoc IndexingContext::getIndexLoc(SourceLocation Loc) const {
|
||||
CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const {
|
||||
CXIdxLoc idxLoc = { {nullptr, nullptr}, 0 };
|
||||
if (Loc.isInvalid())
|
||||
return idxLoc;
|
||||
|
||||
idxLoc.ptr_data[0] = const_cast<IndexingContext *>(this);
|
||||
idxLoc.ptr_data[0] = const_cast<CXIndexDataConsumer *>(this);
|
||||
idxLoc.int_data = Loc.getRawEncoding();
|
||||
return idxLoc;
|
||||
}
|
||||
|
||||
void IndexingContext::translateLoc(SourceLocation Loc,
|
||||
void CXIndexDataConsumer::translateLoc(SourceLocation Loc,
|
||||
CXIdxClientFile *indexFile, CXFile *file,
|
||||
unsigned *line, unsigned *column,
|
||||
unsigned *offset) {
|
||||
@ -912,7 +1118,12 @@ void IndexingContext::translateLoc(SourceLocation Loc,
|
||||
*offset = FileOffset;
|
||||
}
|
||||
|
||||
void IndexingContext::getEntityInfo(const NamedDecl *D,
|
||||
static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K);
|
||||
static CXIdxEntityCXXTemplateKind
|
||||
getEntityKindFromSymbolCXXTemplateKind(SymbolCXXTemplateKind K);
|
||||
static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L);
|
||||
|
||||
void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D,
|
||||
EntityInfo &EntityInfo,
|
||||
ScratchAlloc &SA) {
|
||||
if (!D)
|
||||
@ -922,9 +1133,12 @@ void IndexingContext::getEntityInfo(const NamedDecl *D,
|
||||
EntityInfo.cursor = getCursor(D);
|
||||
EntityInfo.Dcl = D;
|
||||
EntityInfo.IndexCtx = this;
|
||||
EntityInfo.kind = CXIdxEntity_Unexposed;
|
||||
EntityInfo.templateKind = CXIdxEntity_NonTemplate;
|
||||
EntityInfo.lang = CXIdxEntityLang_C;
|
||||
|
||||
SymbolInfo SymInfo = getSymbolInfo(D);
|
||||
EntityInfo.kind = getEntityKindFromSymbolKind(SymInfo.Kind);
|
||||
EntityInfo.templateKind =
|
||||
getEntityKindFromSymbolCXXTemplateKind(SymInfo.TemplateKind);
|
||||
EntityInfo.lang = getEntityLangFromSymbolLang(SymInfo.Lang);
|
||||
|
||||
if (D->hasAttrs()) {
|
||||
EntityInfo.AttrList = AttrListInfo::create(D, *this);
|
||||
@ -932,167 +1146,9 @@ void IndexingContext::getEntityInfo(const NamedDecl *D,
|
||||
EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs();
|
||||
}
|
||||
|
||||
if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
|
||||
switch (TD->getTagKind()) {
|
||||
case TTK_Struct:
|
||||
EntityInfo.kind = CXIdxEntity_Struct; break;
|
||||
case TTK_Union:
|
||||
EntityInfo.kind = CXIdxEntity_Union; break;
|
||||
case TTK_Class:
|
||||
EntityInfo.kind = CXIdxEntity_CXXClass;
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
break;
|
||||
case TTK_Interface:
|
||||
EntityInfo.kind = CXIdxEntity_CXXInterface;
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
break;
|
||||
case TTK_Enum:
|
||||
EntityInfo.kind = CXIdxEntity_Enum; break;
|
||||
}
|
||||
|
||||
if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D))
|
||||
if (!CXXRec->isCLike())
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
|
||||
if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
|
||||
EntityInfo.templateKind = CXIdxEntity_TemplatePartialSpecialization;
|
||||
} else if (isa<ClassTemplateSpecializationDecl>(D)) {
|
||||
EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization;
|
||||
}
|
||||
|
||||
} else {
|
||||
switch (D->getKind()) {
|
||||
case Decl::Typedef:
|
||||
EntityInfo.kind = CXIdxEntity_Typedef; break;
|
||||
case Decl::Function:
|
||||
EntityInfo.kind = CXIdxEntity_Function;
|
||||
break;
|
||||
case Decl::ParmVar:
|
||||
EntityInfo.kind = CXIdxEntity_Variable;
|
||||
break;
|
||||
case Decl::Var:
|
||||
EntityInfo.kind = CXIdxEntity_Variable;
|
||||
if (isa<CXXRecordDecl>(D->getDeclContext())) {
|
||||
EntityInfo.kind = CXIdxEntity_CXXStaticVariable;
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
}
|
||||
break;
|
||||
case Decl::Field:
|
||||
EntityInfo.kind = CXIdxEntity_Field;
|
||||
if (const CXXRecordDecl *
|
||||
CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
|
||||
// FIXME: isPOD check is not sufficient, a POD can contain methods,
|
||||
// we want a isCStructLike check.
|
||||
if (!CXXRec->isPOD())
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
}
|
||||
break;
|
||||
case Decl::EnumConstant:
|
||||
EntityInfo.kind = CXIdxEntity_EnumConstant; break;
|
||||
case Decl::ObjCInterface:
|
||||
EntityInfo.kind = CXIdxEntity_ObjCClass;
|
||||
EntityInfo.lang = CXIdxEntityLang_ObjC;
|
||||
break;
|
||||
case Decl::ObjCProtocol:
|
||||
EntityInfo.kind = CXIdxEntity_ObjCProtocol;
|
||||
EntityInfo.lang = CXIdxEntityLang_ObjC;
|
||||
break;
|
||||
case Decl::ObjCCategory:
|
||||
EntityInfo.kind = CXIdxEntity_ObjCCategory;
|
||||
EntityInfo.lang = CXIdxEntityLang_ObjC;
|
||||
break;
|
||||
case Decl::ObjCMethod:
|
||||
if (cast<ObjCMethodDecl>(D)->isInstanceMethod())
|
||||
EntityInfo.kind = CXIdxEntity_ObjCInstanceMethod;
|
||||
else
|
||||
EntityInfo.kind = CXIdxEntity_ObjCClassMethod;
|
||||
EntityInfo.lang = CXIdxEntityLang_ObjC;
|
||||
break;
|
||||
case Decl::ObjCProperty:
|
||||
EntityInfo.kind = CXIdxEntity_ObjCProperty;
|
||||
EntityInfo.lang = CXIdxEntityLang_ObjC;
|
||||
break;
|
||||
case Decl::ObjCIvar:
|
||||
EntityInfo.kind = CXIdxEntity_ObjCIvar;
|
||||
EntityInfo.lang = CXIdxEntityLang_ObjC;
|
||||
break;
|
||||
case Decl::Namespace:
|
||||
EntityInfo.kind = CXIdxEntity_CXXNamespace;
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
break;
|
||||
case Decl::NamespaceAlias:
|
||||
EntityInfo.kind = CXIdxEntity_CXXNamespaceAlias;
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
break;
|
||||
case Decl::CXXConstructor:
|
||||
EntityInfo.kind = CXIdxEntity_CXXConstructor;
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
break;
|
||||
case Decl::CXXDestructor:
|
||||
EntityInfo.kind = CXIdxEntity_CXXDestructor;
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
break;
|
||||
case Decl::CXXConversion:
|
||||
EntityInfo.kind = CXIdxEntity_CXXConversionFunction;
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
break;
|
||||
case Decl::CXXMethod: {
|
||||
const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
|
||||
if (MD->isStatic())
|
||||
EntityInfo.kind = CXIdxEntity_CXXStaticMethod;
|
||||
else
|
||||
EntityInfo.kind = CXIdxEntity_CXXInstanceMethod;
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
break;
|
||||
}
|
||||
case Decl::ClassTemplate:
|
||||
EntityInfo.kind = CXIdxEntity_CXXClass;
|
||||
EntityInfo.templateKind = CXIdxEntity_Template;
|
||||
break;
|
||||
case Decl::FunctionTemplate:
|
||||
EntityInfo.kind = CXIdxEntity_Function;
|
||||
EntityInfo.templateKind = CXIdxEntity_Template;
|
||||
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
|
||||
cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
|
||||
if (isa<CXXConstructorDecl>(MD))
|
||||
EntityInfo.kind = CXIdxEntity_CXXConstructor;
|
||||
else if (isa<CXXDestructorDecl>(MD))
|
||||
EntityInfo.kind = CXIdxEntity_CXXDestructor;
|
||||
else if (isa<CXXConversionDecl>(MD))
|
||||
EntityInfo.kind = CXIdxEntity_CXXConversionFunction;
|
||||
else {
|
||||
if (MD->isStatic())
|
||||
EntityInfo.kind = CXIdxEntity_CXXStaticMethod;
|
||||
else
|
||||
EntityInfo.kind = CXIdxEntity_CXXInstanceMethod;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Decl::TypeAliasTemplate:
|
||||
EntityInfo.kind = CXIdxEntity_CXXTypeAlias;
|
||||
EntityInfo.templateKind = CXIdxEntity_Template;
|
||||
break;
|
||||
case Decl::TypeAlias:
|
||||
EntityInfo.kind = CXIdxEntity_CXXTypeAlias;
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (EntityInfo.kind == CXIdxEntity_Unexposed)
|
||||
return;
|
||||
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
if (FD->getTemplatedKind() ==
|
||||
FunctionDecl::TK_FunctionTemplateSpecialization)
|
||||
EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization;
|
||||
}
|
||||
|
||||
if (EntityInfo.templateKind != CXIdxEntity_NonTemplate)
|
||||
EntityInfo.lang = CXIdxEntityLang_CXX;
|
||||
|
||||
if (IdentifierInfo *II = D->getIdentifier()) {
|
||||
EntityInfo.name = SA.toCStr(II->getName());
|
||||
|
||||
@ -1119,14 +1175,14 @@ void IndexingContext::getEntityInfo(const NamedDecl *D,
|
||||
}
|
||||
}
|
||||
|
||||
void IndexingContext::getContainerInfo(const DeclContext *DC,
|
||||
void CXIndexDataConsumer::getContainerInfo(const DeclContext *DC,
|
||||
ContainerInfo &ContInfo) {
|
||||
ContInfo.cursor = getCursor(cast<Decl>(DC));
|
||||
ContInfo.DC = DC;
|
||||
ContInfo.IndexCtx = this;
|
||||
}
|
||||
|
||||
CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
|
||||
CXCursor CXIndexDataConsumer::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
|
||||
if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
|
||||
return MakeCursorTypeRef(TD, Loc, CXTU);
|
||||
if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
|
||||
@ -1147,7 +1203,7 @@ CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
|
||||
return clang_getNullCursor();
|
||||
}
|
||||
|
||||
bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
|
||||
bool CXIndexDataConsumer::shouldIgnoreIfImplicit(const Decl *D) {
|
||||
if (isa<ObjCInterfaceDecl>(D))
|
||||
return false;
|
||||
if (isa<ObjCCategoryDecl>(D))
|
||||
@ -1161,7 +1217,7 @@ bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
|
||||
bool CXIndexDataConsumer::isTemplateImplicitInstantiation(const Decl *D) {
|
||||
if (const ClassTemplateSpecializationDecl *
|
||||
SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
|
||||
return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
|
||||
@ -1171,3 +1227,60 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K) {
|
||||
switch (K) {
|
||||
case SymbolKind::Unknown:
|
||||
case SymbolKind::Module:
|
||||
case SymbolKind::Macro:
|
||||
return CXIdxEntity_Unexposed;
|
||||
|
||||
case SymbolKind::Enum: return CXIdxEntity_Enum;
|
||||
case SymbolKind::Struct: return CXIdxEntity_Struct;
|
||||
case SymbolKind::Union: return CXIdxEntity_Union;
|
||||
case SymbolKind::Typedef: return CXIdxEntity_Typedef;
|
||||
case SymbolKind::Function: return CXIdxEntity_Function;
|
||||
case SymbolKind::Variable: return CXIdxEntity_Variable;
|
||||
case SymbolKind::Field: return CXIdxEntity_Field;
|
||||
case SymbolKind::EnumConstant: return CXIdxEntity_EnumConstant;
|
||||
case SymbolKind::ObjCClass: return CXIdxEntity_ObjCClass;
|
||||
case SymbolKind::ObjCProtocol: return CXIdxEntity_ObjCProtocol;
|
||||
case SymbolKind::ObjCCategory: return CXIdxEntity_ObjCCategory;
|
||||
case SymbolKind::ObjCInstanceMethod: return CXIdxEntity_ObjCInstanceMethod;
|
||||
case SymbolKind::ObjCClassMethod: return CXIdxEntity_ObjCClassMethod;
|
||||
case SymbolKind::ObjCProperty: return CXIdxEntity_ObjCProperty;
|
||||
case SymbolKind::ObjCIvar: return CXIdxEntity_ObjCIvar;
|
||||
case SymbolKind::CXXClass: return CXIdxEntity_CXXClass;
|
||||
case SymbolKind::CXXNamespace: return CXIdxEntity_CXXNamespace;
|
||||
case SymbolKind::CXXNamespaceAlias: return CXIdxEntity_CXXNamespaceAlias;
|
||||
case SymbolKind::CXXStaticVariable: return CXIdxEntity_CXXStaticVariable;
|
||||
case SymbolKind::CXXStaticMethod: return CXIdxEntity_CXXStaticMethod;
|
||||
case SymbolKind::CXXInstanceMethod: return CXIdxEntity_CXXInstanceMethod;
|
||||
case SymbolKind::CXXConstructor: return CXIdxEntity_CXXConstructor;
|
||||
case SymbolKind::CXXDestructor: return CXIdxEntity_CXXDestructor;
|
||||
case SymbolKind::CXXConversionFunction:
|
||||
return CXIdxEntity_CXXConversionFunction;
|
||||
case SymbolKind::CXXTypeAlias: return CXIdxEntity_CXXTypeAlias;
|
||||
case SymbolKind::CXXInterface: return CXIdxEntity_CXXInterface;
|
||||
}
|
||||
}
|
||||
|
||||
static CXIdxEntityCXXTemplateKind
|
||||
getEntityKindFromSymbolCXXTemplateKind(SymbolCXXTemplateKind K) {
|
||||
switch (K) {
|
||||
case SymbolCXXTemplateKind::NonTemplate: return CXIdxEntity_NonTemplate;
|
||||
case SymbolCXXTemplateKind::Template: return CXIdxEntity_Template;
|
||||
case SymbolCXXTemplateKind::TemplatePartialSpecialization:
|
||||
return CXIdxEntity_TemplatePartialSpecialization;
|
||||
case SymbolCXXTemplateKind::TemplateSpecialization:
|
||||
return CXIdxEntity_TemplateSpecialization;
|
||||
}
|
||||
}
|
||||
|
||||
static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
|
||||
switch (L) {
|
||||
case SymbolLanguage::C: return CXIdxEntityLang_C;
|
||||
case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC;
|
||||
case SymbolLanguage::CXX: return CXIdxEntityLang_CXX;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
//===- IndexingContext.h - Higher level API functions -----------*- C++ -*-===//
|
||||
//===- CXIndexDataConsumer.h - Index data consumer for libclang--*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -7,11 +7,12 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H
|
||||
#define LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H
|
||||
#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
|
||||
#define LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
|
||||
|
||||
#include "CXCursor.h"
|
||||
#include "Index_Internal.h"
|
||||
#include "clang/Index/IndexDataConsumer.h"
|
||||
#include "clang/AST/DeclGroup.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
@ -27,14 +28,14 @@ namespace clang {
|
||||
class ClassTemplateSpecializationDecl;
|
||||
|
||||
namespace cxindex {
|
||||
class IndexingContext;
|
||||
class CXIndexDataConsumer;
|
||||
class AttrListInfo;
|
||||
|
||||
class ScratchAlloc {
|
||||
IndexingContext &IdxCtx;
|
||||
CXIndexDataConsumer &IdxCtx;
|
||||
|
||||
public:
|
||||
explicit ScratchAlloc(IndexingContext &indexCtx);
|
||||
explicit ScratchAlloc(CXIndexDataConsumer &indexCtx);
|
||||
ScratchAlloc(const ScratchAlloc &SA);
|
||||
|
||||
~ScratchAlloc();
|
||||
@ -48,7 +49,7 @@ public:
|
||||
|
||||
struct EntityInfo : public CXIdxEntityInfo {
|
||||
const NamedDecl *Dcl;
|
||||
IndexingContext *IndexCtx;
|
||||
CXIndexDataConsumer *IndexCtx;
|
||||
IntrusiveRefCntPtr<AttrListInfo> AttrList;
|
||||
|
||||
EntityInfo() {
|
||||
@ -60,7 +61,7 @@ struct EntityInfo : public CXIdxEntityInfo {
|
||||
|
||||
struct ContainerInfo : public CXIdxContainerInfo {
|
||||
const DeclContext *DC;
|
||||
IndexingContext *IndexCtx;
|
||||
CXIndexDataConsumer *IndexCtx;
|
||||
};
|
||||
|
||||
struct DeclInfo : public CXIdxDeclInfo {
|
||||
@ -248,10 +249,10 @@ class AttrListInfo {
|
||||
AttrListInfo(const AttrListInfo &) = delete;
|
||||
void operator=(const AttrListInfo &) = delete;
|
||||
public:
|
||||
AttrListInfo(const Decl *D, IndexingContext &IdxCtx);
|
||||
AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx);
|
||||
|
||||
static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
|
||||
IndexingContext &IdxCtx);
|
||||
CXIndexDataConsumer &IdxCtx);
|
||||
|
||||
const CXIdxAttrInfo *const *getAttrs() const {
|
||||
if (CXAttrs.empty())
|
||||
@ -273,7 +274,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class IndexingContext {
|
||||
class CXIndexDataConsumer : public index::IndexDataConsumer {
|
||||
ASTContext *Ctx;
|
||||
CXClientData ClientData;
|
||||
IndexerCallbacks &CB;
|
||||
@ -308,7 +309,7 @@ class IndexingContext {
|
||||
}
|
||||
|
||||
ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
|
||||
IndexingContext &IdxCtx,
|
||||
CXIndexDataConsumer &IdxCtx,
|
||||
ScratchAlloc &SA);
|
||||
};
|
||||
|
||||
@ -323,7 +324,7 @@ class IndexingContext {
|
||||
unsigned getNumBases() const { return (unsigned)CXBases.size(); }
|
||||
|
||||
CXXBasesListInfo(const CXXRecordDecl *D,
|
||||
IndexingContext &IdxCtx, ScratchAlloc &SA);
|
||||
CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA);
|
||||
|
||||
private:
|
||||
SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
|
||||
@ -332,13 +333,14 @@ class IndexingContext {
|
||||
friend class AttrListInfo;
|
||||
|
||||
public:
|
||||
IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks,
|
||||
CXIndexDataConsumer(CXClientData clientData, IndexerCallbacks &indexCallbacks,
|
||||
unsigned indexOptions, CXTranslationUnit cxTU)
|
||||
: Ctx(nullptr), ClientData(clientData), CB(indexCallbacks),
|
||||
IndexOptions(indexOptions), CXTU(cxTU),
|
||||
StrScratch(), StrAdapterCount(0) { }
|
||||
|
||||
ASTContext &getASTContext() const { return *Ctx; }
|
||||
CXTranslationUnit getCXTU() const { return CXTU; }
|
||||
|
||||
void setASTContext(ASTContext &ctx);
|
||||
void setPreprocessor(Preprocessor &PP);
|
||||
@ -391,6 +393,8 @@ public:
|
||||
void indexBody(const Stmt *S, const NamedDecl *Parent,
|
||||
const DeclContext *DC = nullptr);
|
||||
|
||||
void indexDiagnostics();
|
||||
|
||||
void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
|
||||
|
||||
bool handleFunction(const FunctionDecl *FD);
|
||||
@ -458,6 +462,17 @@ public:
|
||||
static bool isTemplateImplicitInstantiation(const Decl *D);
|
||||
|
||||
private:
|
||||
bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
|
||||
ArrayRef<index::SymbolRelation> Relations,
|
||||
FileID FID, unsigned Offset,
|
||||
ASTNodeInfo ASTNode) override;
|
||||
|
||||
bool handleModuleOccurence(const ImportDecl *ImportD,
|
||||
index::SymbolRoleSet Roles,
|
||||
FileID FID, unsigned Offset) override;
|
||||
|
||||
void finish() override;
|
||||
|
||||
bool handleDecl(const NamedDecl *D,
|
||||
SourceLocation Loc, CXCursor Cursor,
|
||||
DeclInfo &DInfo,
|
||||
@ -495,7 +510,7 @@ private:
|
||||
static bool shouldIgnoreIfImplicit(const Decl *D);
|
||||
};
|
||||
|
||||
inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
|
||||
inline ScratchAlloc::ScratchAlloc(CXIndexDataConsumer &idxCtx) : IdxCtx(idxCtx) {
|
||||
++IdxCtx.StrAdapterCount;
|
||||
}
|
||||
inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
|
@ -1,224 +0,0 @@
|
||||
//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IndexingContext.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace cxindex;
|
||||
|
||||
namespace {
|
||||
|
||||
class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
|
||||
IndexingContext &IndexCtx;
|
||||
const NamedDecl *Parent;
|
||||
const DeclContext *ParentDC;
|
||||
|
||||
typedef RecursiveASTVisitor<BodyIndexer> base;
|
||||
public:
|
||||
BodyIndexer(IndexingContext &indexCtx,
|
||||
const NamedDecl *Parent, const DeclContext *DC)
|
||||
: IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
|
||||
|
||||
bool shouldWalkTypesOfTypeLocs() const { return false; }
|
||||
|
||||
bool TraverseTypeLoc(TypeLoc TL) {
|
||||
IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
|
||||
IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitDeclRefExpr(DeclRefExpr *E) {
|
||||
IndexCtx.handleReference(E->getDecl(), E->getLocation(),
|
||||
Parent, ParentDC, E);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitMemberExpr(MemberExpr *E) {
|
||||
IndexCtx.handleReference(E->getMemberDecl(), E->getMemberLoc(),
|
||||
Parent, ParentDC, E);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
|
||||
IndexCtx.handleReference(E->getDecl(), E->getLocation(),
|
||||
Parent, ParentDC, E);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
|
||||
if (ObjCMethodDecl *MD = E->getMethodDecl())
|
||||
IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
|
||||
Parent, ParentDC, E,
|
||||
E->isImplicit() ? CXIdxEntityRef_Implicit
|
||||
: CXIdxEntityRef_Direct);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
|
||||
if (E->isExplicitProperty())
|
||||
IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
|
||||
Parent, ParentDC, E);
|
||||
|
||||
// No need to do a handleReference for the objc method, because there will
|
||||
// be a message expr as part of PseudoObjectExpr.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
|
||||
IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), Parent,
|
||||
ParentDC, E, CXIdxEntityRef_Direct);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
|
||||
IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
|
||||
Parent, ParentDC, E, CXIdxEntityRef_Direct);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
|
||||
if (ObjCMethodDecl *MD = E->getBoxingMethod())
|
||||
IndexCtx.handleReference(MD, E->getLocStart(),
|
||||
Parent, ParentDC, E, CXIdxEntityRef_Implicit);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
|
||||
if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod())
|
||||
IndexCtx.handleReference(MD, E->getLocStart(),
|
||||
Parent, ParentDC, E, CXIdxEntityRef_Implicit);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
|
||||
if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod())
|
||||
IndexCtx.handleReference(MD, E->getLocStart(),
|
||||
Parent, ParentDC, E, CXIdxEntityRef_Implicit);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitCXXConstructExpr(CXXConstructExpr *E) {
|
||||
IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
|
||||
Parent, ParentDC, E);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
|
||||
DataRecursionQueue *Q = nullptr) {
|
||||
if (E->getOperatorLoc().isInvalid())
|
||||
return true; // implicit.
|
||||
return base::TraverseCXXOperatorCallExpr(E, Q);
|
||||
}
|
||||
|
||||
bool VisitDeclStmt(DeclStmt *S) {
|
||||
if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
|
||||
IndexCtx.indexDeclGroupRef(S->getDeclGroup());
|
||||
return true;
|
||||
}
|
||||
|
||||
DeclGroupRef DG = S->getDeclGroup();
|
||||
for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
|
||||
const Decl *D = *I;
|
||||
if (!D)
|
||||
continue;
|
||||
if (!IndexCtx.isFunctionLocalDecl(D))
|
||||
IndexCtx.indexTopLevelDecl(D);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
|
||||
if (C->capturesThis() || C->capturesVLAType())
|
||||
return true;
|
||||
|
||||
if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
|
||||
IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), Parent,
|
||||
ParentDC);
|
||||
|
||||
// FIXME: Lambda init-captures.
|
||||
return true;
|
||||
}
|
||||
|
||||
// RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
|
||||
// the things that we visit. Make sure to only visit the semantic form.
|
||||
// Also visit things that are in the syntactic form but not the semantic one,
|
||||
// for example the indices in DesignatedInitExprs.
|
||||
bool TraverseInitListExpr(InitListExpr *S) {
|
||||
|
||||
class SyntacticFormIndexer :
|
||||
public RecursiveASTVisitor<SyntacticFormIndexer> {
|
||||
IndexingContext &IndexCtx;
|
||||
const NamedDecl *Parent;
|
||||
const DeclContext *ParentDC;
|
||||
|
||||
public:
|
||||
SyntacticFormIndexer(IndexingContext &indexCtx,
|
||||
const NamedDecl *Parent, const DeclContext *DC)
|
||||
: IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
|
||||
|
||||
bool shouldWalkTypesOfTypeLocs() const { return false; }
|
||||
|
||||
bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
|
||||
for (DesignatedInitExpr::reverse_designators_iterator
|
||||
D = E->designators_rbegin(), DEnd = E->designators_rend();
|
||||
D != DEnd; ++D) {
|
||||
if (D->isFieldDesignator())
|
||||
IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
|
||||
Parent, ParentDC, E);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
auto visitForm = [&](InitListExpr *Form) {
|
||||
for (Stmt *SubStmt : Form->children()) {
|
||||
if (!TraverseStmt(SubStmt))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
|
||||
InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
|
||||
|
||||
if (SemaForm) {
|
||||
// Visit things present in syntactic form but not the semantic form.
|
||||
if (SyntaxForm) {
|
||||
SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
|
||||
}
|
||||
return visitForm(SemaForm);
|
||||
}
|
||||
|
||||
// No semantic, try the syntactic.
|
||||
if (SyntaxForm) {
|
||||
return visitForm(SyntaxForm);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
|
||||
const DeclContext *DC) {
|
||||
if (!S)
|
||||
return;
|
||||
|
||||
if (!DC)
|
||||
DC = Parent->getLexicalDeclContext();
|
||||
BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IndexingContext.h"
|
||||
#include "CXIndexDataConsumer.h"
|
||||
#include "CIndexDiagnostic.h"
|
||||
#include "CIndexer.h"
|
||||
#include "CLog.h"
|
||||
@ -16,12 +16,12 @@
|
||||
#include "CXString.h"
|
||||
#include "CXTranslationUnit.h"
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
#include "clang/Frontend/ASTUnit.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Frontend/CompilerInvocation.h"
|
||||
#include "clang/Frontend/FrontendAction.h"
|
||||
#include "clang/Frontend/Utils.h"
|
||||
#include "clang/Index/IndexingAction.h"
|
||||
#include "clang/Lex/HeaderSearch.h"
|
||||
#include "clang/Lex/PPCallbacks.h"
|
||||
#include "clang/Lex/PPConditionalDirectiveRecord.h"
|
||||
@ -34,11 +34,10 @@
|
||||
#include <cstdio>
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::index;
|
||||
using namespace cxtu;
|
||||
using namespace cxindex;
|
||||
|
||||
static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx);
|
||||
|
||||
namespace {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -224,12 +223,12 @@ private:
|
||||
|
||||
class IndexPPCallbacks : public PPCallbacks {
|
||||
Preprocessor &PP;
|
||||
IndexingContext &IndexCtx;
|
||||
CXIndexDataConsumer &DataConsumer;
|
||||
bool IsMainFileEntered;
|
||||
|
||||
public:
|
||||
IndexPPCallbacks(Preprocessor &PP, IndexingContext &indexCtx)
|
||||
: PP(PP), IndexCtx(indexCtx), IsMainFileEntered(false) { }
|
||||
IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer)
|
||||
: PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { }
|
||||
|
||||
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
|
||||
SrcMgr::CharacteristicKind FileType, FileID PrevFID) override {
|
||||
@ -241,7 +240,7 @@ public:
|
||||
|
||||
if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) {
|
||||
IsMainFileEntered = true;
|
||||
IndexCtx.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID()));
|
||||
DataConsumer.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,7 +251,7 @@ public:
|
||||
const Module *Imported) override {
|
||||
bool isImport = (IncludeTok.is(tok::identifier) &&
|
||||
IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import);
|
||||
IndexCtx.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
|
||||
DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
|
||||
Imported);
|
||||
}
|
||||
|
||||
@ -279,18 +278,18 @@ public:
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class IndexingConsumer : public ASTConsumer {
|
||||
IndexingContext &IndexCtx;
|
||||
CXIndexDataConsumer &DataConsumer;
|
||||
TUSkipBodyControl *SKCtrl;
|
||||
|
||||
public:
|
||||
IndexingConsumer(IndexingContext &indexCtx, TUSkipBodyControl *skCtrl)
|
||||
: IndexCtx(indexCtx), SKCtrl(skCtrl) { }
|
||||
IndexingConsumer(CXIndexDataConsumer &dataConsumer, TUSkipBodyControl *skCtrl)
|
||||
: DataConsumer(dataConsumer), SKCtrl(skCtrl) { }
|
||||
|
||||
// ASTConsumer Implementation
|
||||
|
||||
void Initialize(ASTContext &Context) override {
|
||||
IndexCtx.setASTContext(Context);
|
||||
IndexCtx.startedTranslationUnit();
|
||||
DataConsumer.setASTContext(Context);
|
||||
DataConsumer.startedTranslationUnit();
|
||||
}
|
||||
|
||||
void HandleTranslationUnit(ASTContext &Ctx) override {
|
||||
@ -299,34 +298,7 @@ public:
|
||||
}
|
||||
|
||||
bool HandleTopLevelDecl(DeclGroupRef DG) override {
|
||||
IndexCtx.indexDeclGroupRef(DG);
|
||||
return !IndexCtx.shouldAbort();
|
||||
}
|
||||
|
||||
/// \brief Handle the specified top-level declaration that occurred inside
|
||||
/// and ObjC container.
|
||||
void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
|
||||
IndexCtx.indexDeclGroupRef(DG);
|
||||
}
|
||||
|
||||
/// \brief This is called by the AST reader when deserializing things.
|
||||
/// The default implementation forwards to HandleTopLevelDecl but we don't
|
||||
/// care about them when indexing, so have an empty definition.
|
||||
void HandleInterestingDecl(DeclGroupRef D) override {}
|
||||
|
||||
void HandleTagDeclDefinition(TagDecl *D) override {
|
||||
if (!IndexCtx.shouldIndexImplicitTemplateInsts())
|
||||
return;
|
||||
|
||||
if (IndexCtx.isTemplateImplicitInstantiation(D))
|
||||
IndexCtx.indexDecl(D);
|
||||
}
|
||||
|
||||
void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override {
|
||||
if (!IndexCtx.shouldIndexImplicitTemplateInsts())
|
||||
return;
|
||||
|
||||
IndexCtx.indexDecl(D);
|
||||
return !DataConsumer.shouldAbort();
|
||||
}
|
||||
|
||||
bool shouldSkipFunctionBody(Decl *D) override {
|
||||
@ -335,7 +307,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
const SourceManager &SM = IndexCtx.getASTContext().getSourceManager();
|
||||
const SourceManager &SM = DataConsumer.getASTContext().getSourceManager();
|
||||
SourceLocation Loc = D->getLocation();
|
||||
if (Loc.isMacroID())
|
||||
return false;
|
||||
@ -376,34 +348,29 @@ public:
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class IndexingFrontendAction : public ASTFrontendAction {
|
||||
IndexingContext IndexCtx;
|
||||
CXTranslationUnit CXTU;
|
||||
std::shared_ptr<CXIndexDataConsumer> DataConsumer;
|
||||
|
||||
SessionSkipBodyData *SKData;
|
||||
std::unique_ptr<TUSkipBodyControl> SKCtrl;
|
||||
|
||||
public:
|
||||
IndexingFrontendAction(CXClientData clientData,
|
||||
IndexerCallbacks &indexCallbacks,
|
||||
unsigned indexOptions,
|
||||
CXTranslationUnit cxTU,
|
||||
IndexingFrontendAction(std::shared_ptr<CXIndexDataConsumer> dataConsumer,
|
||||
SessionSkipBodyData *skData)
|
||||
: IndexCtx(clientData, indexCallbacks, indexOptions, cxTU),
|
||||
CXTU(cxTU), SKData(skData) { }
|
||||
: DataConsumer(dataConsumer), SKData(skData) { }
|
||||
|
||||
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
||||
StringRef InFile) override {
|
||||
PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
|
||||
|
||||
if (!PPOpts.ImplicitPCHInclude.empty()) {
|
||||
IndexCtx.importedPCH(
|
||||
DataConsumer->importedPCH(
|
||||
CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude));
|
||||
}
|
||||
|
||||
IndexCtx.setASTContext(CI.getASTContext());
|
||||
DataConsumer->setASTContext(CI.getASTContext());
|
||||
Preprocessor &PP = CI.getPreprocessor();
|
||||
PP.addPPCallbacks(llvm::make_unique<IndexPPCallbacks>(PP, IndexCtx));
|
||||
IndexCtx.setPreprocessor(PP);
|
||||
PP.addPPCallbacks(llvm::make_unique<IndexPPCallbacks>(PP, *DataConsumer));
|
||||
DataConsumer->setPreprocessor(PP);
|
||||
|
||||
if (SKData) {
|
||||
auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager());
|
||||
@ -411,15 +378,11 @@ public:
|
||||
SKCtrl = llvm::make_unique<TUSkipBodyControl>(*SKData, *PPRec, PP);
|
||||
}
|
||||
|
||||
return llvm::make_unique<IndexingConsumer>(IndexCtx, SKCtrl.get());
|
||||
}
|
||||
|
||||
void EndSourceFileAction() override {
|
||||
indexDiagnostics(CXTU, IndexCtx);
|
||||
return llvm::make_unique<IndexingConsumer>(*DataConsumer, SKCtrl.get());
|
||||
}
|
||||
|
||||
TranslationUnitKind getTranslationUnitKind() override {
|
||||
if (IndexCtx.shouldIndexImplicitTemplateInsts())
|
||||
if (DataConsumer->shouldIndexImplicitTemplateInsts())
|
||||
return TU_Complete;
|
||||
else
|
||||
return TU_Prefix;
|
||||
@ -431,6 +394,13 @@ public:
|
||||
// clang_indexSourceFileUnit Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) {
|
||||
IndexingOptions IdxOpts;
|
||||
if (index_options & CXIndexOpt_IndexFunctionLocalSymbols)
|
||||
IdxOpts.IndexFunctionLocals = true;
|
||||
return IdxOpts;
|
||||
}
|
||||
|
||||
struct IndexSessionData {
|
||||
CXIndex CIdx;
|
||||
std::unique_ptr<SessionSkipBodyData> SkipBodyData;
|
||||
@ -566,13 +536,17 @@ static CXErrorCode clang_indexSourceFile_Impl(
|
||||
if (SkipBodies)
|
||||
CInvok->getFrontendOpts().SkipFunctionBodies = true;
|
||||
|
||||
std::unique_ptr<IndexingFrontendAction> IndexAction;
|
||||
IndexAction.reset(new IndexingFrontendAction(client_data, CB,
|
||||
index_options, CXTU->getTU(),
|
||||
SkipBodies ? IdxSession->SkipBodyData.get() : nullptr));
|
||||
auto DataConsumer =
|
||||
std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options,
|
||||
CXTU->getTU());
|
||||
auto InterAction = llvm::make_unique<IndexingFrontendAction>(DataConsumer,
|
||||
SkipBodies ? IdxSession->SkipBodyData.get() : nullptr);
|
||||
std::unique_ptr<FrontendAction> IndexAction;
|
||||
IndexAction = createIndexingAction(std::move(InterAction), DataConsumer,
|
||||
getIndexingOptionsFromCXOptions(index_options));
|
||||
|
||||
// Recover resources if we crash before exiting this method.
|
||||
llvm::CrashRecoveryContextCleanupRegistrar<IndexingFrontendAction>
|
||||
llvm::CrashRecoveryContextCleanupRegistrar<FrontendAction>
|
||||
IndexActionCleanup(IndexAction.get());
|
||||
|
||||
bool Persistent = requestedToGetTU;
|
||||
@ -632,7 +606,7 @@ static CXErrorCode clang_indexSourceFile_Impl(
|
||||
// clang_indexTranslationUnit Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) {
|
||||
static void indexPreprocessingRecord(ASTUnit &Unit, CXIndexDataConsumer &IdxCtx) {
|
||||
Preprocessor &PP = Unit.getPreprocessor();
|
||||
if (!PP.getPreprocessingRecord())
|
||||
return;
|
||||
@ -655,24 +629,6 @@ static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool topLevelDeclVisitor(void *context, const Decl *D) {
|
||||
IndexingContext &IdxCtx = *static_cast<IndexingContext*>(context);
|
||||
IdxCtx.indexTopLevelDecl(D);
|
||||
return !IdxCtx.shouldAbort();
|
||||
}
|
||||
|
||||
static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) {
|
||||
Unit.visitLocalTopLevelDecls(&IdxCtx, topLevelDeclVisitor);
|
||||
}
|
||||
|
||||
static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx) {
|
||||
if (!IdxCtx.hasDiagnosticCallback())
|
||||
return;
|
||||
|
||||
CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(TU);
|
||||
IdxCtx.handleDiagnosticSet(DiagSet);
|
||||
}
|
||||
|
||||
static CXErrorCode clang_indexTranslationUnit_Impl(
|
||||
CXIndexAction idxAction, CXClientData client_data,
|
||||
IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size,
|
||||
@ -696,19 +652,8 @@ static CXErrorCode clang_indexTranslationUnit_Impl(
|
||||
? index_callbacks_size : sizeof(CB);
|
||||
memcpy(&CB, client_index_callbacks, ClientCBSize);
|
||||
|
||||
std::unique_ptr<IndexingContext> IndexCtx;
|
||||
IndexCtx.reset(new IndexingContext(client_data, CB, index_options, TU));
|
||||
|
||||
// Recover resources if we crash before exiting this method.
|
||||
llvm::CrashRecoveryContextCleanupRegistrar<IndexingContext>
|
||||
IndexCtxCleanup(IndexCtx.get());
|
||||
|
||||
std::unique_ptr<IndexingConsumer> IndexConsumer;
|
||||
IndexConsumer.reset(new IndexingConsumer(*IndexCtx, nullptr));
|
||||
|
||||
// Recover resources if we crash before exiting this method.
|
||||
llvm::CrashRecoveryContextCleanupRegistrar<IndexingConsumer>
|
||||
IndexConsumerCleanup(IndexConsumer.get());
|
||||
auto DataConsumer = std::make_shared<CXIndexDataConsumer>(client_data, CB,
|
||||
index_options, TU);
|
||||
|
||||
ASTUnit *Unit = cxtu::getASTUnit(TU);
|
||||
if (!Unit)
|
||||
@ -717,20 +662,21 @@ static CXErrorCode clang_indexTranslationUnit_Impl(
|
||||
ASTUnit::ConcurrencyCheck Check(*Unit);
|
||||
|
||||
if (const FileEntry *PCHFile = Unit->getPCHFile())
|
||||
IndexCtx->importedPCH(PCHFile);
|
||||
DataConsumer->importedPCH(PCHFile);
|
||||
|
||||
FileManager &FileMgr = Unit->getFileManager();
|
||||
|
||||
if (Unit->getOriginalSourceFileName().empty())
|
||||
IndexCtx->enteredMainFile(nullptr);
|
||||
DataConsumer->enteredMainFile(nullptr);
|
||||
else
|
||||
IndexCtx->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName()));
|
||||
DataConsumer->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName()));
|
||||
|
||||
IndexConsumer->Initialize(Unit->getASTContext());
|
||||
DataConsumer->setASTContext(Unit->getASTContext());
|
||||
DataConsumer->startedTranslationUnit();
|
||||
|
||||
indexPreprocessingRecord(*Unit, *IndexCtx);
|
||||
indexTranslationUnit(*Unit, *IndexCtx);
|
||||
indexDiagnostics(TU, *IndexCtx);
|
||||
indexPreprocessingRecord(*Unit, *DataConsumer);
|
||||
indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options));
|
||||
DataConsumer->indexDiagnostics();
|
||||
|
||||
return CXError_Success;
|
||||
}
|
||||
@ -1015,9 +961,9 @@ void clang_indexLoc_getFileLocation(CXIdxLoc location,
|
||||
if (!location.ptr_data[0] || Loc.isInvalid())
|
||||
return;
|
||||
|
||||
IndexingContext &IndexCtx =
|
||||
*static_cast<IndexingContext*>(location.ptr_data[0]);
|
||||
IndexCtx.translateLoc(Loc, indexFile, file, line, column, offset);
|
||||
CXIndexDataConsumer &DataConsumer =
|
||||
*static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
|
||||
DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset);
|
||||
}
|
||||
|
||||
CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
|
||||
@ -1025,9 +971,9 @@ CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
|
||||
if (!location.ptr_data[0] || Loc.isInvalid())
|
||||
return clang_getNullLocation();
|
||||
|
||||
IndexingContext &IndexCtx =
|
||||
*static_cast<IndexingContext*>(location.ptr_data[0]);
|
||||
return cxloc::translateSourceLocation(IndexCtx.getASTContext(), Loc);
|
||||
CXIndexDataConsumer &DataConsumer =
|
||||
*static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
|
||||
return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc);
|
||||
}
|
||||
|
||||
} // end: extern "C"
|
||||
|
Loading…
x
Reference in New Issue
Block a user