mirror of
https://github.com/MaskRay/ccls.git
synced 2025-02-07 17:32:14 +00:00
parent
dd4044998d
commit
6a8537c2bf
141
src/indexer.cc
141
src/indexer.cc
@ -393,24 +393,43 @@ std::string GetDocumentContentInRange(CXTranslationUnit cx_tu,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
bool IsFunctionCallContext(CXCursorKind kind) {
|
||||||
ClangCursor parent,
|
switch (kind) {
|
||||||
void* client_data) {
|
case CXCursor_FunctionDecl:
|
||||||
switch (cursor.get_kind()) {
|
case CXCursor_CXXMethod:
|
||||||
default:
|
case CXCursor_Constructor:
|
||||||
cursor.VisitChildren(&TemplateVisitor, client_data);
|
case CXCursor_Destructor:
|
||||||
/* fallthrough */
|
case CXCursor_ConversionFunction:
|
||||||
case CXCursor_FunctionTemplate:
|
case CXCursor_FunctionTemplate:
|
||||||
case CXCursor_ClassTemplate:
|
case CXCursor_OverloadedDeclRef:
|
||||||
return ClangCursor::VisitResult::Continue;
|
// TODO: we need to test lambdas
|
||||||
case CXCursor_OverloadedDeclRef: {
|
case CXCursor_LambdaExpr:
|
||||||
unsigned num_overloaded = clang_getNumOverloadedDecls(cursor.cx_cursor);
|
return true;
|
||||||
for (unsigned i = 0; i != num_overloaded; i++) {
|
|
||||||
// ClangCursor overloaded = clang_getOverloadedDecl(cursor.cx_cursor, i);
|
default:
|
||||||
// TODO handle references
|
break;
|
||||||
}
|
}
|
||||||
return ClangCursor::VisitResult::Continue;
|
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnIndexReference_Function(IndexFile* db,
|
||||||
|
Range loc_spelling,
|
||||||
|
ClangCursor caller_cursor,
|
||||||
|
IndexFunc* called,
|
||||||
|
const std::string& called_usr,
|
||||||
|
bool is_implicit) {
|
||||||
|
if (IsFunctionCallContext(caller_cursor.get_kind())) {
|
||||||
|
IndexFuncId caller_id = db->ToFuncId(caller_cursor.cx_cursor);
|
||||||
|
IndexFunc* caller = db->Resolve(caller_id);
|
||||||
|
// Calling db->ToFuncId invalidates the FuncDef* ptrs.
|
||||||
|
|
||||||
|
AddFuncRef(&caller->def.callees,
|
||||||
|
IndexFuncRef(called->id, loc_spelling, is_implicit));
|
||||||
|
AddFuncRef(&called->callers,
|
||||||
|
IndexFuncRef(caller->id, loc_spelling, is_implicit));
|
||||||
|
} else {
|
||||||
|
AddFuncRef(&called->callers, IndexFuncRef(loc_spelling, is_implicit));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1005,6 +1024,52 @@ ClangCursor::VisitResult VisitMacroDefinitionAndExpansions(ClangCursor cursor,
|
|||||||
return ClangCursor::VisitResult::Continue;
|
return ClangCursor::VisitResult::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct TemplateVisitorData {
|
||||||
|
IndexFile* db;
|
||||||
|
ClangCursor container;
|
||||||
|
};
|
||||||
|
|
||||||
|
ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
||||||
|
ClangCursor parent,
|
||||||
|
TemplateVisitorData* data) {
|
||||||
|
switch (cursor.get_kind()) {
|
||||||
|
default:
|
||||||
|
if (!IsFunctionCallContext(cursor.get_kind()))
|
||||||
|
cursor.VisitChildren(&TemplateVisitor, data);
|
||||||
|
/* fallthrough */
|
||||||
|
// TODO Add other containers not covered by IsFunctionCallContext
|
||||||
|
case CXCursor_ClassTemplate:
|
||||||
|
return ClangCursor::VisitResult::Continue;
|
||||||
|
case CXCursor_OverloadedDeclRef: {
|
||||||
|
unsigned num_overloaded = clang_getNumOverloadedDecls(cursor.cx_cursor);
|
||||||
|
for (unsigned i = 0; i != num_overloaded; i++) {
|
||||||
|
ClangCursor overloaded = clang_getOverloadedDecl(cursor.cx_cursor, i);
|
||||||
|
switch (overloaded.get_kind()) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case CXCursor_FunctionDecl: {
|
||||||
|
std::string ref_usr = overloaded.get_usr();
|
||||||
|
IndexFuncId called_id = data->db->ToFuncId(ref_usr);
|
||||||
|
IndexFunc* called = data->db->Resolve(called_id);
|
||||||
|
OnIndexReference_Function(data->db,
|
||||||
|
ResolveSpelling(cursor.cx_cursor),
|
||||||
|
data->container,
|
||||||
|
called,
|
||||||
|
ref_usr,
|
||||||
|
/*implicit=*/ false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ClangCursor::VisitResult::Continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||||
if (!kIndexStdDeclarations &&
|
if (!kIndexStdDeclarations &&
|
||||||
clang_Location_isInSystemHeader(
|
clang_Location_isInSystemHeader(
|
||||||
@ -1281,7 +1346,10 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
// references.
|
// references.
|
||||||
if (decl->entityInfo->templateKind == CXIdxEntity_Template) {
|
if (decl->entityInfo->templateKind == CXIdxEntity_Template) {
|
||||||
// TODO put db and caller into client data
|
// TODO put db and caller into client data
|
||||||
decl_cursor.VisitChildren(&TemplateVisitor, (void*)0);
|
TemplateVisitorData data;
|
||||||
|
data.db = db;
|
||||||
|
data.container = decl_cursor;
|
||||||
|
decl_cursor.VisitChildren(&TemplateVisitor, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add function usage information. We only want to do it once per
|
// Add function usage information. We only want to do it once per
|
||||||
@ -1470,26 +1538,6 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsFunctionCallContext(CXCursorKind kind) {
|
|
||||||
switch (kind) {
|
|
||||||
case CXCursor_FunctionDecl:
|
|
||||||
case CXCursor_CXXMethod:
|
|
||||||
case CXCursor_Constructor:
|
|
||||||
case CXCursor_Destructor:
|
|
||||||
case CXCursor_ConversionFunction:
|
|
||||||
case CXCursor_FunctionTemplate:
|
|
||||||
case CXCursor_OverloadedDeclRef:
|
|
||||||
// TODO: we need to test lambdas
|
|
||||||
case CXCursor_LambdaExpr:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
||||||
// TODO: Use clang_getFileUniqueID
|
// TODO: Use clang_getFileUniqueID
|
||||||
CXFile file;
|
CXFile file;
|
||||||
@ -1592,19 +1640,10 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
!CursorSpellingContainsString(ref->cursor, param->tu->cx_tu,
|
!CursorSpellingContainsString(ref->cursor, param->tu->cx_tu,
|
||||||
called->def.short_name)));
|
called->def.short_name)));
|
||||||
|
|
||||||
if (IsFunctionCallContext(ref->container->cursor.kind)) {
|
OnIndexReference_Function(db, loc_spelling,
|
||||||
IndexFuncId caller_id = db->ToFuncId(ref->container->cursor);
|
ref->container->cursor,
|
||||||
IndexFunc* caller = db->Resolve(caller_id);
|
called,
|
||||||
// Calling db->ToFuncId invalidates the FuncDef* ptrs.
|
ref->referencedEntity->USR, is_implicit);
|
||||||
called = db->Resolve(called_id);
|
|
||||||
|
|
||||||
AddFuncRef(&caller->def.callees,
|
|
||||||
IndexFuncRef(called_id, loc_spelling, is_implicit));
|
|
||||||
AddFuncRef(&called->callers,
|
|
||||||
IndexFuncRef(caller_id, loc_spelling, is_implicit));
|
|
||||||
} else {
|
|
||||||
AddFuncRef(&called->callers, IndexFuncRef(loc_spelling, is_implicit));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if |str| starts with |start|. Ignores case.
|
// Checks if |str| starts with |start|. Ignores case.
|
||||||
auto str_begin = [](const char* start, const char* str) {
|
auto str_begin = [](const char* start, const char* str) {
|
||||||
|
@ -82,7 +82,7 @@ constexpr int kCamelScore = kWordStartScore + kGapScore - 1;
|
|||||||
|
|
||||||
enum class CharClass { Lower, Upper, Digit, NonWord };
|
enum class CharClass { Lower, Upper, Digit, NonWord };
|
||||||
|
|
||||||
static enum CharClass GetCharClass(int c) {
|
static CharClass GetCharClass(int c) {
|
||||||
if (islower(c)) return CharClass::Lower;
|
if (islower(c)) return CharClass::Lower;
|
||||||
if (isupper(c)) return CharClass::Upper;
|
if (isupper(c)) return CharClass::Upper;
|
||||||
if (isdigit(c)) return CharClass::Digit;
|
if (isdigit(c)) return CharClass::Digit;
|
||||||
|
Loading…
Reference in New Issue
Block a user