Move libclangmm/Cursor.* to clang_cursor.*

This commit is contained in:
Jacob Dufault 2017-11-11 11:31:05 -08:00
parent 5fa7fbf0d2
commit 348b4a2e4e
8 changed files with 368 additions and 535 deletions

View File

@ -1,6 +1,5 @@
// Place your settings in this file to overwrite default and user settings. // Place your settings in this file to overwrite default and user settings.
{ {
"cquery.cacheDirectory": "C:/Users/jacob/Desktop/cquery/CACHE",
"cquery.blacklist": [ "cquery.blacklist": [
// ".*libclangmm/.*" // ".*libclangmm/.*"
], ],
@ -9,5 +8,6 @@
], ],
"cquery.launch.command": "cquery.exe", "cquery.launch.command": "cquery.exe",
"cquery.launch.workingDirectory": "C:/Users/jacob/Desktop/cquery/x64/Release", "cquery.launch.workingDirectory": "C:/Users/jacob/Desktop/cquery/x64/Release",
"cquery.launch.autoRestart": false "cquery.launch.autoRestart": false,
"cquery.cacheDirectory": "c:/Users/jacob/Desktop/cquery/src/.vscode/cquery_cached_index/"
} }

195
src/clang_cursor.cc Normal file
View File

@ -0,0 +1,195 @@
#include "clang_cursor.h"
#include "clang_utils.h"
#include <algorithm>
#include <cassert>
ClangType::ClangType() : cx_type() {}
ClangType::ClangType(const CXType& other) : cx_type(other) {}
bool ClangType::operator==(const ClangType& rhs) const {
return clang_equalTypes(cx_type, rhs.cx_type);
}
bool ClangType::is_fundamental() const {
// NOTE: This will return false for pointed types. Should we call
// strip_qualifiers for the user?
return cx_type.kind >= CXType_FirstBuiltin &&
cx_type.kind <= CXType_LastBuiltin;
}
CXCursor ClangType::get_declaration() const {
return clang_getTypeDeclaration(cx_type);
}
std::string ClangType::get_usr() const {
return ClangCursor(clang_getTypeDeclaration(cx_type)).get_usr();
}
ClangType ClangType::get_canonical() const {
return clang_getCanonicalType(cx_type);
}
ClangType ClangType::strip_qualifiers() const {
// CXRefQualifierKind qualifiers = clang_Type_getCXXRefQualifier(cx_type)
switch (cx_type.kind) {
case CXType_LValueReference:
case CXType_Pointer:
return clang_getPointeeType(cx_type);
default:
break;
}
return cx_type;
}
std::string ClangType::get_spelling() const {
return ToString(clang_getTypeSpelling(cx_type));
}
ClangType ClangType::get_return_type() const {
return ClangType(clang_getResultType(cx_type));
}
std::vector<ClangType> ClangType::get_arguments() const {
int size = clang_getNumArgTypes(cx_type);
assert(size >= 0);
if (size < 0)
return std::vector<ClangType>();
std::vector<ClangType> types(size);
for (int i = 0; i < size; ++i)
types.emplace_back(clang_getArgType(cx_type, i));
return types;
}
std::vector<ClangType> ClangType::get_template_arguments() const {
int size = clang_Type_getNumTemplateArguments(cx_type);
assert(size >= 0);
if (size < 0)
return std::vector<ClangType>();
std::vector<ClangType> types(size);
for (int i = 0; i < size; ++i)
types.emplace_back(clang_Type_getTemplateArgumentAsType(cx_type, i));
return types;
}
static_assert(sizeof(ClangCursor) == sizeof(CXCursor),
"Cursor must be the same size as CXCursor");
ClangCursor::ClangCursor() : cx_cursor(clang_getNullCursor()) {}
ClangCursor::ClangCursor(const CXCursor& other) : cx_cursor(other) {}
ClangCursor::operator bool() const {
return !clang_Cursor_isNull(cx_cursor);
}
bool ClangCursor::operator==(const ClangCursor& rhs) const {
return clang_equalCursors(cx_cursor, rhs.cx_cursor);
}
bool ClangCursor::operator!=(const ClangCursor& rhs) const {
return !(*this == rhs);
}
CXCursorKind ClangCursor::get_kind() const {
return cx_cursor.kind;
}
ClangCursor ClangCursor::get_declaration() const {
ClangType type = get_type();
// auto x = new Foo() will not be deduced to |Foo| if we do not use the
// canonical type. However, a canonical type will look past typedefs so we
// will not accurately report variables on typedefs if we always do this.
if (type.cx_type.kind == CXType_Auto)
type = type.get_canonical();
return type.strip_qualifiers().get_declaration();
}
ClangType ClangCursor::get_type() const {
return ClangType(clang_getCursorType(cx_cursor));
}
std::string ClangCursor::get_spelling() const {
return ::ToString(clang_getCursorSpelling(cx_cursor));
}
std::string ClangCursor::get_display_name() const {
return ::ToString(clang_getCursorDisplayName(cx_cursor));
}
std::string ClangCursor::get_usr() const {
return ::ToString(clang_getCursorUSR(cx_cursor));
}
bool ClangCursor::is_definition() const {
return clang_isCursorDefinition(cx_cursor);
}
ClangCursor ClangCursor::template_specialization_to_template_definition()
const {
CXCursor definition = clang_getSpecializedCursorTemplate(cx_cursor);
if (definition.kind == CXCursor_FirstInvalid)
return cx_cursor;
return definition;
}
ClangCursor ClangCursor::get_referenced() const {
return ClangCursor(clang_getCursorReferenced(cx_cursor));
}
ClangCursor ClangCursor::get_canonical() const {
return ClangCursor(clang_getCanonicalCursor(cx_cursor));
}
ClangCursor ClangCursor::get_definition() const {
return ClangCursor(clang_getCursorDefinition(cx_cursor));
}
ClangCursor ClangCursor::get_semantic_parent() const {
return ClangCursor(clang_getCursorSemanticParent(cx_cursor));
}
std::vector<ClangCursor> ClangCursor::get_arguments() const {
int size = clang_Cursor_getNumArguments(cx_cursor);
if (size < 0)
return std::vector<ClangCursor>();
std::vector<ClangCursor> cursors(size);
for (int i = 0; i < size; ++i)
cursors.emplace_back(clang_Cursor_getArgument(cx_cursor, i));
return cursors;
}
bool ClangCursor::is_valid_kind() const {
CXCursor referenced = clang_getCursorReferenced(cx_cursor);
if (clang_Cursor_isNull(referenced))
return false;
CXCursorKind kind = get_kind();
return kind > CXCursor_UnexposedDecl &&
(kind < CXCursor_FirstInvalid || kind > CXCursor_LastInvalid);
}
std::string ClangCursor::get_type_description() const {
auto type = clang_getCursorType(cx_cursor);
return ::ToString(clang_getTypeSpelling(type));
}
std::string ClangCursor::get_comments() const {
ClangCursor referenced = get_referenced();
if (referenced)
return ::ToString(clang_Cursor_getRawCommentText(referenced.cx_cursor));
return "";
}
std::string ClangCursor::ToString() const {
return ::ToString(get_kind()) + " " + get_spelling();
}

87
src/clang_cursor.h Normal file
View File

@ -0,0 +1,87 @@
#pragma once
#include <clang-c/Index.h>
#include <string>
#include <vector>
class ClangType {
public:
ClangType();
ClangType(const CXType& other);
bool operator==(const ClangType& rhs) const;
// Returns true if this is a fundamental type like int.
bool is_fundamental() const;
// ClangCursor is not defined so we have to return CXCursor
CXCursor get_declaration() const;
std::string get_usr() const;
std::string get_spelling() const;
ClangType get_canonical() const;
// Try to resolve this type and remove qualifies, ie, Foo* will become Foo
ClangType strip_qualifiers() const;
ClangType get_return_type() const;
std::vector<ClangType> get_arguments() const;
std::vector<ClangType> get_template_arguments() const;
CXType cx_type;
};
class ClangCursor {
public:
ClangCursor();
ClangCursor(const CXCursor& other);
explicit operator bool() const;
bool operator==(const ClangCursor& rhs) const;
bool operator!=(const ClangCursor& rhs) const;
CXCursorKind get_kind() const;
ClangCursor get_declaration() const;
ClangType get_type() const;
std::string get_spelling() const;
std::string get_display_name() const;
std::string get_usr() const;
bool is_definition() const;
// If the given cursor points to a template specialization, this
// will return the cursor pointing to the template definition.
// If the given cursor is not a template specialization, this will
// just return the same cursor.
//
// This means it is always safe to call this method.
ClangCursor template_specialization_to_template_definition() const;
ClangCursor get_referenced() const;
ClangCursor get_canonical() const;
ClangCursor get_definition() const;
ClangCursor get_semantic_parent() const;
std::vector<ClangCursor> get_arguments() const;
bool is_valid_kind() const;
std::string get_type_description() const;
std::string get_comments() const;
std::string ToString() const;
enum class VisitResult { Break, Continue, Recurse };
template <typename TClientData>
using Visitor = VisitResult (*)(ClangCursor cursor,
ClangCursor parent,
TClientData* client_data);
template <typename TClientData>
void VisitChildren(Visitor<TClientData> visitor,
TClientData* client_data) const {
clang_visitChildren(cx_cursor, reinterpret_cast<CXCursorVisitor>(visitor),
client_data);
}
CXCursor cx_cursor;
};

View File

@ -1,7 +1,7 @@
#include "indexer.h" #include "indexer.h"
#include "clang_cursor.h"
#include "clang_utils.h" #include "clang_utils.h"
#include "libclangmm/Cursor.h"
#include "libclangmm/Index.h" #include "libclangmm/Index.h"
#include "libclangmm/TranslationUnit.h" #include "libclangmm/TranslationUnit.h"
#include "platform.h" #include "platform.h"
@ -58,7 +58,7 @@ struct NamespaceHelper {
const CXIdxContainerInfo* container, const CXIdxContainerInfo* container,
std::string qualified_name) { std::string qualified_name) {
if (container) { if (container) {
std::string container_usr = clang::Cursor(container->cursor).get_usr(); std::string container_usr = ClangCursor(container->cursor).get_usr();
auto it = container_usr_to_qualified_name.find(container_usr); auto it = container_usr_to_qualified_name.find(container_usr);
if (it != container_usr_to_qualified_name.end()) { if (it != container_usr_to_qualified_name.end()) {
container_usr_to_qualified_name[usr] = container_usr_to_qualified_name[usr] =
@ -73,7 +73,7 @@ struct NamespaceHelper {
std::string QualifiedName(const CXIdxContainerInfo* container, std::string QualifiedName(const CXIdxContainerInfo* container,
std::string unqualified_name) { std::string unqualified_name) {
if (container) { if (container) {
std::string container_usr = clang::Cursor(container->cursor).get_usr(); std::string container_usr = ClangCursor(container->cursor).get_usr();
auto it = container_usr_to_qualified_name.find(container_usr); auto it = container_usr_to_qualified_name.find(container_usr);
if (it != container_usr_to_qualified_name.end()) if (it != container_usr_to_qualified_name.end())
return it->second + unqualified_name; return it->second + unqualified_name;
@ -81,7 +81,7 @@ struct NamespaceHelper {
// Anonymous namespaces are not processed by indexDeclaration. If we // Anonymous namespaces are not processed by indexDeclaration. If we
// encounter one insert it into map. // encounter one insert it into map.
if (container->cursor.kind == CXCursor_Namespace) { if (container->cursor.kind == CXCursor_Namespace) {
// assert(clang::Cursor(container->cursor).get_spelling() == ""); // assert(ClangCursor(container->cursor).get_spelling() == "");
container_usr_to_qualified_name[container_usr] = "::"; container_usr_to_qualified_name[container_usr] = "::";
return "::" + unqualified_name; return "::" + unqualified_name;
} }
@ -103,10 +103,10 @@ struct ConstructorCache {
std::unordered_map<Usr, std::vector<Constructor>> constructors_; std::unordered_map<Usr, std::vector<Constructor>> constructors_;
// This should be called whenever there is a constructor declaration. // This should be called whenever there is a constructor declaration.
void NotifyConstructor(clang::Cursor ctor_cursor) { void NotifyConstructor(ClangCursor ctor_cursor) {
auto build_type_desc = [](clang::Cursor cursor) { auto build_type_desc = [](ClangCursor cursor) {
std::vector<std::string> type_desc; std::vector<std::string> type_desc;
for (clang::Cursor arg : cursor.get_arguments()) { for (ClangCursor arg : cursor.get_arguments()) {
if (arg.get_kind() == CXCursor_ParmDecl) if (arg.get_kind() == CXCursor_ParmDecl)
type_desc.push_back(arg.get_type_description()); type_desc.push_back(arg.get_type_description());
} }
@ -419,15 +419,15 @@ IndexVarId IndexFile::ToVarId(const std::string& usr) {
} }
IndexTypeId IndexFile::ToTypeId(const CXCursor& cursor) { IndexTypeId IndexFile::ToTypeId(const CXCursor& cursor) {
return ToTypeId(clang::Cursor(cursor).get_usr()); return ToTypeId(ClangCursor(cursor).get_usr());
} }
IndexFuncId IndexFile::ToFuncId(const CXCursor& cursor) { IndexFuncId IndexFile::ToFuncId(const CXCursor& cursor) {
return ToFuncId(clang::Cursor(cursor).get_usr()); return ToFuncId(ClangCursor(cursor).get_usr());
} }
IndexVarId IndexFile::ToVarId(const CXCursor& cursor) { IndexVarId IndexFile::ToVarId(const CXCursor& cursor) {
return ToVarId(clang::Cursor(cursor).get_usr()); return ToVarId(ClangCursor(cursor).get_usr());
} }
IndexType* IndexFile::Resolve(IndexTypeId id) { IndexType* IndexFile::Resolve(IndexTypeId id) {
@ -546,9 +546,9 @@ CXIdxClientContainer startedTranslationUnit(CXClientData client_data,
return nullptr; return nullptr;
} }
clang::VisiterResult DumpVisitor(clang::Cursor cursor, ClangCursor::VisitResult DumpVisitor(ClangCursor cursor,
clang::Cursor parent, ClangCursor parent,
int* level) { int* level) {
for (int i = 0; i < *level; ++i) for (int i = 0; i < *level; ++i)
std::cerr << " "; std::cerr << " ";
std::cerr << ToString(cursor.get_kind()) << " " << cursor.get_spelling() std::cerr << ToString(cursor.get_kind()) << " " << cursor.get_spelling()
@ -558,56 +558,55 @@ clang::VisiterResult DumpVisitor(clang::Cursor cursor,
cursor.VisitChildren(&DumpVisitor, level); cursor.VisitChildren(&DumpVisitor, level);
*level -= 1; *level -= 1;
return clang::VisiterResult::Continue; return ClangCursor::VisitResult::Continue;
} }
void Dump(clang::Cursor cursor) { void Dump(ClangCursor cursor) {
int level = 0; int level = 0;
cursor.VisitChildren(&DumpVisitor, &level); cursor.VisitChildren(&DumpVisitor, &level);
} }
struct FindChildOfKindParam { struct FindChildOfKindParam {
CXCursorKind target_kind; CXCursorKind target_kind;
optional<clang::Cursor> result; optional<ClangCursor> result;
FindChildOfKindParam(CXCursorKind target_kind) : target_kind(target_kind) {} FindChildOfKindParam(CXCursorKind target_kind) : target_kind(target_kind) {}
}; };
clang::VisiterResult FindChildOfKindVisitor(clang::Cursor cursor, ClangCursor::VisitResult FindChildOfKindVisitor(ClangCursor cursor,
clang::Cursor parent, ClangCursor parent,
FindChildOfKindParam* param) { FindChildOfKindParam* param) {
if (cursor.get_kind() == param->target_kind) { if (cursor.get_kind() == param->target_kind) {
param->result = cursor; param->result = cursor;
return clang::VisiterResult::Break; return ClangCursor::VisitResult::Break;
} }
return clang::VisiterResult::Recurse; return ClangCursor::VisitResult::Recurse;
} }
optional<clang::Cursor> FindChildOfKind(clang::Cursor cursor, optional<ClangCursor> FindChildOfKind(ClangCursor cursor, CXCursorKind kind) {
CXCursorKind kind) {
FindChildOfKindParam param(kind); FindChildOfKindParam param(kind);
cursor.VisitChildren(&FindChildOfKindVisitor, &param); cursor.VisitChildren(&FindChildOfKindVisitor, &param);
return param.result; return param.result;
} }
clang::VisiterResult FindTypeVisitor(clang::Cursor cursor, ClangCursor::VisitResult FindTypeVisitor(ClangCursor cursor,
clang::Cursor parent, ClangCursor parent,
optional<clang::Cursor>* result) { optional<ClangCursor>* result) {
switch (cursor.get_kind()) { switch (cursor.get_kind()) {
case CXCursor_TypeRef: case CXCursor_TypeRef:
case CXCursor_TemplateRef: case CXCursor_TemplateRef:
*result = cursor; *result = cursor;
return clang::VisiterResult::Break; return ClangCursor::VisitResult::Break;
default: default:
break; break;
} }
return clang::VisiterResult::Recurse; return ClangCursor::VisitResult::Recurse;
} }
optional<clang::Cursor> FindType(clang::Cursor cursor) { optional<ClangCursor> FindType(ClangCursor cursor) {
optional<clang::Cursor> result; optional<ClangCursor> result;
cursor.VisitChildren(&FindTypeVisitor, &result); cursor.VisitChildren(&FindTypeVisitor, &result);
return result; return result;
} }
@ -630,13 +629,13 @@ bool IsTypeDefinition(const CXIdxContainerInfo* container) {
struct VisitDeclForTypeUsageParam { struct VisitDeclForTypeUsageParam {
IndexFile* db; IndexFile* db;
int has_processed_any = false; int has_processed_any = false;
optional<clang::Cursor> previous_cursor; optional<ClangCursor> previous_cursor;
optional<IndexTypeId> initial_type; optional<IndexTypeId> initial_type;
VisitDeclForTypeUsageParam(IndexFile* db) : db(db) {} VisitDeclForTypeUsageParam(IndexFile* db) : db(db) {}
}; };
void VisitDeclForTypeUsageVisitorHandler(clang::Cursor cursor, void VisitDeclForTypeUsageVisitorHandler(ClangCursor cursor,
VisitDeclForTypeUsageParam* param) { VisitDeclForTypeUsageParam* param) {
param->has_processed_any = true; param->has_processed_any = true;
IndexFile* db = param->db; IndexFile* db = param->db;
@ -661,9 +660,9 @@ void VisitDeclForTypeUsageVisitorHandler(clang::Cursor cursor,
UniqueAdd(ref_type_def->uses, loc); UniqueAdd(ref_type_def->uses, loc);
} }
clang::VisiterResult VisitDeclForTypeUsageVisitor( ClangCursor::VisitResult VisitDeclForTypeUsageVisitor(
clang::Cursor cursor, ClangCursor cursor,
clang::Cursor parent, ClangCursor parent,
VisitDeclForTypeUsageParam* param) { VisitDeclForTypeUsageParam* param) {
switch (cursor.get_kind()) { switch (cursor.get_kind()) {
case CXCursor_TemplateRef: case CXCursor_TemplateRef:
@ -674,7 +673,7 @@ clang::VisiterResult VisitDeclForTypeUsageVisitor(
} }
param->previous_cursor = cursor; param->previous_cursor = cursor;
return clang::VisiterResult::Continue; return ClangCursor::VisitResult::Continue;
// We do not want to recurse for everything, since if we do that we will end // We do not want to recurse for everything, since if we do that we will end
// up visiting method definition bodies/etc. Instead, we only recurse for // up visiting method definition bodies/etc. Instead, we only recurse for
@ -689,13 +688,13 @@ clang::VisiterResult VisitDeclForTypeUsageVisitor(
case CXCursor_CStyleCastExpr: case CXCursor_CStyleCastExpr:
case CXCursor_CXXStaticCastExpr: case CXCursor_CXXStaticCastExpr:
case CXCursor_CXXReinterpretCastExpr: case CXCursor_CXXReinterpretCastExpr:
return clang::VisiterResult::Recurse; return ClangCursor::VisitResult::Recurse;
default: default:
return clang::VisiterResult::Continue; return ClangCursor::VisitResult::Continue;
} }
return clang::VisiterResult::Continue; return ClangCursor::VisitResult::Continue;
} }
// Finds the cursor associated with the declaration type of |cursor|. This // Finds the cursor associated with the declaration type of |cursor|. This
@ -703,8 +702,8 @@ clang::VisiterResult VisitDeclForTypeUsageVisitor(
// qualifies from |cursor| (ie, Foo* => Foo) and removes template arguments // qualifies from |cursor| (ie, Foo* => Foo) and removes template arguments
// (ie, Foo<A,B> => Foo<*,*>). // (ie, Foo<A,B> => Foo<*,*>).
optional<IndexTypeId> ResolveToDeclarationType(IndexFile* db, optional<IndexTypeId> ResolveToDeclarationType(IndexFile* db,
clang::Cursor cursor) { ClangCursor cursor) {
clang::Cursor declaration = cursor.get_declaration(); ClangCursor declaration = cursor.get_declaration();
declaration = declaration.template_specialization_to_template_definition(); declaration = declaration.template_specialization_to_template_definition();
std::string usr = declaration.get_usr(); std::string usr = declaration.get_usr();
if (usr != "") if (usr != "")
@ -719,7 +718,7 @@ optional<IndexTypeId> ResolveToDeclarationType(IndexFile* db,
// ResolveToDeclarationType, which works in more scenarios. // ResolveToDeclarationType, which works in more scenarios.
optional<IndexTypeId> AddDeclTypeUsages( optional<IndexTypeId> AddDeclTypeUsages(
IndexFile* db, IndexFile* db,
clang::Cursor decl_cursor, ClangCursor decl_cursor,
const CXIdxContainerInfo* semantic_container, const CXIdxContainerInfo* semantic_container,
const CXIdxContainerInfo* lexical_container) { const CXIdxContainerInfo* lexical_container) {
// std::cerr << std::endl << "AddDeclUsages " << decl_cursor.get_spelling() << // std::cerr << std::endl << "AddDeclUsages " << decl_cursor.get_spelling() <<
@ -817,7 +816,7 @@ optional<IndexTypeId> AddDeclTypeUsages(
// //
if (!decl_cursor.is_definition()) { if (!decl_cursor.is_definition()) {
// TODO: I don't think this resolution ever works. // TODO: I don't think this resolution ever works.
clang::Cursor def = decl_cursor.get_definition(); ClangCursor def = decl_cursor.get_definition();
if (def.get_kind() != CXCursor_FirstInvalid) { if (def.get_kind() != CXCursor_FirstInvalid) {
std::cerr << "Successful resolution of decl usage to definition" std::cerr << "Successful resolution of decl usage to definition"
<< std::endl; << std::endl;
@ -851,9 +850,9 @@ optional<IndexTypeId> AddDeclTypeUsages(
// Various versions of LLVM (ie, 4.0) will not visit inline variable references // Various versions of LLVM (ie, 4.0) will not visit inline variable references
// for template arguments. // for template arguments.
clang::VisiterResult AddDeclInitializerUsagesVisitor(clang::Cursor cursor, ClangCursor::VisitResult AddDeclInitializerUsagesVisitor(ClangCursor cursor,
clang::Cursor parent, ClangCursor parent,
IndexFile* db) { IndexFile* db) {
/* /*
We need to index the |DeclRefExpr| below (ie, |var| inside of We need to index the |DeclRefExpr| below (ie, |var| inside of
Foo<int>::var). Foo<int>::var).
@ -882,7 +881,7 @@ clang::VisiterResult AddDeclInitializerUsagesVisitor(clang::Cursor cursor,
// TODO: when we resolve the template type to the definition, we get a // TODO: when we resolve the template type to the definition, we get a
// different USR. // different USR.
// clang::Cursor ref = // ClangCursor ref =
// cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr(); // cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr();
// std::string ref_usr = // std::string ref_usr =
// cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr(); // cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr();
@ -907,10 +906,10 @@ clang::VisiterResult AddDeclInitializerUsagesVisitor(clang::Cursor cursor,
break; break;
} }
return clang::VisiterResult::Recurse; return ClangCursor::VisitResult::Recurse;
} }
void AddDeclInitializerUsages(IndexFile* db, clang::Cursor decl_cursor) { void AddDeclInitializerUsages(IndexFile* db, ClangCursor decl_cursor) {
decl_cursor.VisitChildren(&AddDeclInitializerUsagesVisitor, db); decl_cursor.VisitChildren(&AddDeclInitializerUsagesVisitor, db);
} }
@ -924,9 +923,9 @@ bool AreEqualLocations(CXIdxLoc loc, CXCursor cursor) {
clang_getRangeStart(clang_Cursor_getSpellingNameRange(cursor, 0, 0))); clang_getRangeStart(clang_Cursor_getSpellingNameRange(cursor, 0, 0)));
} }
clang::VisiterResult VisitMacroDefinitionAndExpansions(clang::Cursor cursor, ClangCursor::VisitResult VisitMacroDefinitionAndExpansions(ClangCursor cursor,
clang::Cursor parent, ClangCursor parent,
IndexParam* param) { IndexParam* param) {
switch (cursor.get_kind()) { switch (cursor.get_kind()) {
case CXCursor_MacroDefinition: case CXCursor_MacroDefinition:
case CXCursor_MacroExpansion: { case CXCursor_MacroExpansion: {
@ -972,7 +971,7 @@ clang::VisiterResult VisitMacroDefinitionAndExpansions(clang::Cursor cursor,
break; break;
} }
return clang::VisiterResult::Continue; return ClangCursor::VisitResult::Continue;
} }
void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
@ -1017,7 +1016,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
case CXIdxEntity_CXXStaticVariable: { case CXIdxEntity_CXXStaticVariable: {
Range decl_loc_spelling = ResolveSpelling(decl->cursor); Range decl_loc_spelling = ResolveSpelling(decl->cursor);
clang::Cursor decl_cursor = decl->cursor; ClangCursor decl_cursor = decl->cursor;
// Do not index implicit template instantiations. // Do not index implicit template instantiations.
if (decl_cursor != if (decl_cursor !=
@ -1109,8 +1108,8 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
Range decl_spelling = ResolveSpelling(decl->cursor); Range decl_spelling = ResolveSpelling(decl->cursor);
Range decl_extent = ResolveExtent(decl->cursor); Range decl_extent = ResolveExtent(decl->cursor);
clang::Cursor decl_cursor = decl->cursor; ClangCursor decl_cursor = decl->cursor;
clang::Cursor decl_cursor_resolved = ClangCursor decl_cursor_resolved =
decl_cursor.template_specialization_to_template_definition(); decl_cursor.template_specialization_to_template_definition();
bool is_template_specialization = decl_cursor != decl_cursor_resolved; bool is_template_specialization = decl_cursor != decl_cursor_resolved;
@ -1140,7 +1139,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
param->tu->cx_tu, clang_getCursorExtent(decl->cursor)); param->tu->cx_tu, clang_getCursorExtent(decl->cursor));
// Add parameters. // Add parameters.
for (clang::Cursor arg : decl_cursor.get_arguments()) { for (ClangCursor arg : decl_cursor.get_arguments()) {
switch (arg.get_kind()) { switch (arg.get_kind()) {
case CXCursor_ParmDecl: { case CXCursor_ParmDecl: {
Range param_spelling = ResolveSpelling(arg.cx_cursor); Range param_spelling = ResolveSpelling(arg.cx_cursor);
@ -1217,7 +1216,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
<< func->def.detailed_name << std::endl; << func->def.detailed_name << std::endl;
for (unsigned i = 0; i < num_overridden; ++i) { for (unsigned i = 0; i < num_overridden; ++i) {
clang::Cursor parent = overridden[i]; ClangCursor parent = overridden[i];
IndexFuncId parent_id = db->ToFuncId(parent.get_usr()); IndexFuncId parent_id = db->ToFuncId(parent.get_usr());
IndexFunc* parent_def = db->Resolve(parent_id); IndexFunc* parent_def = db->Resolve(parent_id);
func = db->Resolve(func_id); // ToFuncId invalidated func_def func = db->Resolve(func_id); // ToFuncId invalidated func_def
@ -1325,7 +1324,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
default: default:
std::cerr << "!! Unhandled indexDeclaration: " std::cerr << "!! Unhandled indexDeclaration: "
<< clang::Cursor(decl->cursor).ToString() << " at " << ClangCursor(decl->cursor).ToString() << " at "
<< ResolveSpelling(decl->cursor).start.ToString() << std::endl; << ResolveSpelling(decl->cursor).start.ToString() << std::endl;
std::cerr << " entityInfo->kind = " << decl->entityInfo->kind std::cerr << " entityInfo->kind = " << decl->entityInfo->kind
<< std::endl; << std::endl;
@ -1333,15 +1332,15 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
<< std::endl; << std::endl;
if (decl->declAsContainer) if (decl->declAsContainer)
std::cerr << " declAsContainer = " std::cerr << " declAsContainer = "
<< clang::Cursor(decl->declAsContainer->cursor).ToString() << ClangCursor(decl->declAsContainer->cursor).ToString()
<< std::endl; << std::endl;
if (decl->semanticContainer) if (decl->semanticContainer)
std::cerr << " semanticContainer = " std::cerr << " semanticContainer = "
<< clang::Cursor(decl->semanticContainer->cursor).ToString() << ClangCursor(decl->semanticContainer->cursor).ToString()
<< std::endl; << std::endl;
if (decl->lexicalContainer) if (decl->lexicalContainer)
std::cerr << " lexicalContainer = " std::cerr << " lexicalContainer = "
<< clang::Cursor(decl->lexicalContainer->cursor).get_usr() << ClangCursor(decl->lexicalContainer->cursor).get_usr()
<< std::endl; << std::endl;
break; break;
} }
@ -1409,7 +1408,7 @@ void indexEntityReference(CXClientData client_data,
// if (!clang_Location_isFromMainFile(clang_getCursorLocation(ref->cursor))) // if (!clang_Location_isFromMainFile(clang_getCursorLocation(ref->cursor)))
// return; // return;
clang::Cursor cursor(ref->cursor); ClangCursor cursor(ref->cursor);
switch (ref->referencedEntity->kind) { switch (ref->referencedEntity->kind) {
case CXIdxEntity_CXXNamespaceAlias: case CXIdxEntity_CXXNamespaceAlias:
@ -1424,7 +1423,7 @@ void indexEntityReference(CXClientData client_data,
case CXIdxEntity_Field: { case CXIdxEntity_Field: {
Range loc_spelling = ResolveSpelling(ref->cursor); Range loc_spelling = ResolveSpelling(ref->cursor);
clang::Cursor referenced = ref->referencedEntity->cursor; ClangCursor referenced = ref->referencedEntity->cursor;
referenced = referenced.template_specialization_to_template_definition(); referenced = referenced.template_specialization_to_template_definition();
IndexVarId var_id = db->ToVarId(referenced.get_usr()); IndexVarId var_id = db->ToVarId(referenced.get_usr());
@ -1494,16 +1493,16 @@ void indexEntityReference(CXClientData client_data,
if (is_template && str_begin("make", ref->referencedEntity->name)) { if (is_template && str_begin("make", ref->referencedEntity->name)) {
// Try to find the return type of called function. That type will have // Try to find the return type of called function. That type will have
// the constructor function we add a usage to. // the constructor function we add a usage to.
optional<clang::Cursor> opt_found_type = FindType(ref->cursor); optional<ClangCursor> opt_found_type = FindType(ref->cursor);
if (opt_found_type) { if (opt_found_type) {
std::string ctor_type_usr = std::string ctor_type_usr =
opt_found_type->get_referenced().get_usr(); opt_found_type->get_referenced().get_usr();
clang::Cursor call_cursor = ref->cursor; ClangCursor call_cursor = ref->cursor;
// Build a type description from the parameters of the call, so we // Build a type description from the parameters of the call, so we
// can try to find a constructor with the same type description. // can try to find a constructor with the same type description.
std::vector<std::string> call_type_desc; std::vector<std::string> call_type_desc;
for (clang::Type type : call_cursor.get_type().get_arguments()) { for (ClangType type : call_cursor.get_type().get_arguments()) {
std::string type_desc = type.get_spelling(); std::string type_desc = type.get_spelling();
if (!type_desc.empty()) if (!type_desc.empty())
call_type_desc.push_back(type_desc); call_type_desc.push_back(type_desc);
@ -1529,7 +1528,7 @@ void indexEntityReference(CXClientData client_data,
case CXIdxEntity_Union: case CXIdxEntity_Union:
case CXIdxEntity_Struct: case CXIdxEntity_Struct:
case CXIdxEntity_CXXClass: { case CXIdxEntity_CXXClass: {
clang::Cursor referenced_cursor = ref->referencedEntity->cursor; ClangCursor referenced_cursor = ref->referencedEntity->cursor;
referenced_cursor = referenced_cursor =
referenced_cursor.template_specialization_to_template_definition(); referenced_cursor.template_specialization_to_template_definition();
IndexTypeId referenced_id = db->ToTypeId(referenced_cursor.get_usr()); IndexTypeId referenced_id = db->ToTypeId(referenced_cursor.get_usr());
@ -1569,15 +1568,15 @@ void indexEntityReference(CXClientData client_data,
std::cerr << " ref->kind = " << ref->kind << std::endl; std::cerr << " ref->kind = " << ref->kind << std::endl;
if (ref->parentEntity) if (ref->parentEntity)
std::cerr << " parentEntity = " std::cerr << " parentEntity = "
<< clang::Cursor(ref->parentEntity->cursor).ToString() << ClangCursor(ref->parentEntity->cursor).ToString()
<< std::endl; << std::endl;
if (ref->referencedEntity) if (ref->referencedEntity)
std::cerr << " referencedEntity = " std::cerr << " referencedEntity = "
<< clang::Cursor(ref->referencedEntity->cursor).ToString() << ClangCursor(ref->referencedEntity->cursor).ToString()
<< std::endl; << std::endl;
if (ref->container) if (ref->container)
std::cerr << " container = " std::cerr << " container = "
<< clang::Cursor(ref->container->cursor).ToString() << ClangCursor(ref->container->cursor).ToString()
<< std::endl; << std::endl;
break; break;
} }
@ -1663,7 +1662,7 @@ std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
clang_IndexAction_dispose(index_action); clang_IndexAction_dispose(index_action);
// std::cerr << "!! [END] Indexing " << file << std::endl; // std::cerr << "!! [END] Indexing " << file << std::endl;
clang::Cursor(clang_getTranslationUnitCursor(tu->cx_tu)) ClangCursor(clang_getTranslationUnitCursor(tu->cx_tu))
.VisitChildren(&VisitMacroDefinitionAndExpansions, &param); .VisitChildren(&VisitMacroDefinitionAndExpansions, &param);
perf->index_build = timer.ElapsedMicrosecondsAndReset(); perf->index_build = timer.ElapsedMicrosecondsAndReset();

View File

@ -1,349 +0,0 @@
#include <algorithm>
#include <cassert>
#include "../clang_utils.h"
#include "Cursor.h"
namespace clang {
Type::Type() : cx_type() {}
Type::Type(const CXType& other) : cx_type(other) {}
bool Type::operator==(const Type& rhs) const {
return clang_equalTypes(cx_type, rhs.cx_type);
}
bool Type::is_fundamental() const {
// switch (cx_type.kind) {
// case CXType_Auto:
// return true;
//}
// NOTE: This will return false for pointed types. Should we call
// strip_qualifiers for the user?
return cx_type.kind >= CXType_FirstBuiltin &&
cx_type.kind <= CXType_LastBuiltin;
}
CXCursor Type::get_declaration() const {
return clang_getTypeDeclaration(cx_type);
}
std::string Type::get_usr() const {
return clang::Cursor(clang_getTypeDeclaration(cx_type)).get_usr();
}
Type Type::get_canonical() const {
return clang_getCanonicalType(cx_type);
}
Type Type::strip_qualifiers() const {
// CXRefQualifierKind qualifiers = clang_Type_getCXXRefQualifier(cx_type)
switch (cx_type.kind) {
case CXType_LValueReference:
case CXType_Pointer:
return clang_getPointeeType(cx_type);
default:
break;
}
return cx_type;
}
std::string Type::get_spelling() const {
return ToString(clang_getTypeSpelling(cx_type));
}
/*
SourceLocation Cursor::get_source_location() const {
return SourceLocation(clang_getCursorLocation(cx_cursor));
}
*/
Type Type::get_return_type() const {
return Type(clang_getResultType(cx_type));
}
std::vector<Type> Type::get_arguments() const {
int size = clang_getNumArgTypes(cx_type);
assert(size >= 0);
if (size < 0)
return std::vector<Type>();
std::vector<Type> types(size);
for (int i = 0; i < size; ++i)
types.emplace_back(clang_getArgType(cx_type, i));
return types;
}
std::vector<Type> Type::get_template_arguments() const {
/*
CINDEX_LINKAGE int clang_Type_getNumTemplateArguments(CXType T);
CINDEX_LINKAGE CXType clang_Type_getTemplateArgumentAsType(CXType T, unsigned
i);
*/
int size = clang_Type_getNumTemplateArguments(cx_type);
assert(size >= 0);
if (size < 0)
return std::vector<Type>();
std::vector<Type> types(size);
for (int i = 0; i < size; ++i)
types.emplace_back(clang_Type_getTemplateArgumentAsType(cx_type, i));
return types;
}
static_assert(sizeof(Cursor) == sizeof(CXCursor),
"Cursor must be the same size as CXCursor");
Cursor::Cursor() : cx_cursor(clang_getNullCursor()) {}
Cursor::Cursor(const CXCursor& other) : cx_cursor(other) {}
Cursor::operator bool() const {
return !clang_Cursor_isNull(cx_cursor);
}
bool Cursor::operator==(const Cursor& rhs) const {
return clang_equalCursors(cx_cursor, rhs.cx_cursor);
}
bool Cursor::operator!=(const Cursor& rhs) const {
return !(*this == rhs);
}
CXCursorKind Cursor::get_kind() const {
return cx_cursor.kind;
}
Cursor Cursor::get_declaration() const {
Type type = get_type();
// auto x = new Foo() will not be deduced to |Foo| if we do not use the
// canonical type. However, a canonical type will look past typedefs so we
// will not accurately report variables on typedefs if we always do this.
if (type.cx_type.kind == CXType_Auto)
type = type.get_canonical();
return type.strip_qualifiers().get_declaration();
}
Type Cursor::get_type() const {
return Type(clang_getCursorType(cx_cursor));
}
/*
SourceRange Cursor::get_source_range() const {
return SourceRange(clang_getCursorExtent(cx_cursor));
}
*/
std::string Cursor::get_spelling() const {
return ::ToString(clang_getCursorSpelling(cx_cursor));
}
std::string Cursor::get_display_name() const {
return ::ToString(clang_getCursorDisplayName(cx_cursor));
}
std::string Cursor::get_usr() const {
return ::ToString(clang_getCursorUSR(cx_cursor));
}
bool Cursor::is_definition() const {
return clang_isCursorDefinition(cx_cursor);
}
Cursor Cursor::template_specialization_to_template_definition() const {
CXCursor definition = clang_getSpecializedCursorTemplate(cx_cursor);
if (definition.kind == CXCursor_FirstInvalid)
return cx_cursor;
return definition;
}
Cursor Cursor::get_referenced() const {
return Cursor(clang_getCursorReferenced(cx_cursor));
}
Cursor Cursor::get_canonical() const {
return Cursor(clang_getCanonicalCursor(cx_cursor));
}
Cursor Cursor::get_definition() const {
return Cursor(clang_getCursorDefinition(cx_cursor));
}
Cursor Cursor::get_semantic_parent() const {
return Cursor(clang_getCursorSemanticParent(cx_cursor));
}
std::vector<Cursor> Cursor::get_arguments() const {
int size = clang_Cursor_getNumArguments(cx_cursor);
if (size < 0)
return std::vector<Cursor>();
std::vector<Cursor> cursors(size);
for (int i = 0; i < size; ++i)
cursors.emplace_back(clang_Cursor_getArgument(cx_cursor, i));
return cursors;
}
bool Cursor::is_valid_kind() const {
CXCursor referenced = clang_getCursorReferenced(cx_cursor);
if (clang_Cursor_isNull(referenced))
return false;
CXCursorKind kind = get_kind();
return kind > CXCursor_UnexposedDecl &&
(kind < CXCursor_FirstInvalid || kind > CXCursor_LastInvalid);
}
std::string Cursor::get_type_description() const {
auto type = clang_getCursorType(cx_cursor);
return ::ToString(clang_getTypeSpelling(type));
#if false
std::string spelling;
auto referenced = clang_getCursorReferenced(cx_cursor);
if (!clang_Cursor_isNull(referenced)) {
auto type = clang_getCursorType(referenced);
spelling = clang::ToString(clang_getTypeSpelling(type));
#if CINDEX_VERSION_MAJOR == 0 && CINDEX_VERSION_MINOR < 32
const std::string auto_str = "auto";
if (spelling.size() >= 4 &&
std::equal(auto_str.begin(), auto_str.end(), spelling.begin())) {
auto canonical_type =
clang_getCanonicalType(clang_getCursorType(cx_cursor));
auto canonical_spelling = ToString(clang_getTypeSpelling(canonical_type));
if (spelling.size() > 5 && spelling[4] == ' ' && spelling[5] == '&' &&
spelling != canonical_spelling)
return canonical_spelling + " &";
else
return canonical_spelling;
}
const std::string const_auto_str = "const auto";
if (spelling.size() >= 10 &&
std::equal(const_auto_str.begin(), const_auto_str.end(),
spelling.begin())) {
auto canonical_type =
clang_getCanonicalType(clang_getCursorType(cx_cursor));
auto canonical_spelling = ToString(clang_getTypeSpelling(canonical_type));
if (spelling.size() > 11 && spelling[10] == ' ' && spelling[11] == '&' &&
spelling != canonical_spelling)
return canonical_spelling + " &";
else
return canonical_spelling;
}
#endif
}
if (spelling.empty())
return get_spelling();
return spelling;
#endif
}
#if false
std::string Cursor::evaluate() const {
CXEvalResult eval = clang_Cursor_Evaluate(cx_cursor);
std::string result;
auto kind = clang_EvalResult_getKind(eval);
switch (clang_EvalResult_getKind(eval)) {
case CXEval_Int:
result = std::to_string(clang_EvalResult_getAsInt(eval));
break;
case CXEval_Float:
result = std::to_string(clang_EvalResult_getAsDouble(eval));
break;
default:
{
const char* r = clang_EvalResult_getAsStr(eval);
if (r)
result = r;
break;
}
}
clang_EvalResult_dispose(eval);
return result;
#if false
typedef enum {
CXEval_Int = 1,
CXEval_Float = 2,
CXEval_ObjCStrLiteral = 3,
CXEval_StrLiteral = 4,
CXEval_CFStr = 5,
CXEval_Other = 6,
CXEval_UnExposed = 0
} CXEvalResultKind;
/**
* \brief Evaluation result of a cursor
*/
typedef void * CXEvalResult;
/**
* \brief If cursor is a statement declaration tries to evaluate the
* statement and if its variable, tries to evaluate its initializer,
* into its corresponding type.
*/
CINDEX_LINKAGE CXEvalResult clang_Cursor_Evaluate(CXCursor C);
/**
* \brief Returns the kind of the evaluated result.
*/
CINDEX_LINKAGE CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E);
/**
* \brief Returns the evaluation result as integer if the
* kind is Int.
*/
CINDEX_LINKAGE int clang_EvalResult_getAsInt(CXEvalResult E);
/**
* \brief Returns the evaluation result as double if the
* kind is double.
*/
CINDEX_LINKAGE double clang_EvalResult_getAsDouble(CXEvalResult E);
/**
* \brief Returns the evaluation result as a constant string if the
* kind is other than Int or float. User must not free this pointer,
* instead call clang_EvalResult_dispose on the CXEvalResult returned
* by clang_Cursor_Evaluate.
*/
CINDEX_LINKAGE const char* clang_EvalResult_getAsStr(CXEvalResult E);
/**
* \brief Disposes the created Eval memory.
*/
CINDEX_LINKAGE void clang_EvalResult_dispose(CXEvalResult E);
#endif
}
#endif
std::string Cursor::get_comments() const {
Cursor referenced = get_referenced();
if (referenced)
return ::ToString(clang_Cursor_getRawCommentText(referenced.cx_cursor));
return "";
}
std::string Cursor::ToString() const {
return ::ToString(get_kind()) + " " + get_spelling();
}
} // namespace clang

View File

@ -1,99 +0,0 @@
#ifndef CURSOR_H_
#define CURSOR_H_
#include <string>
#include <type_traits>
#include <vector>
#include <clang-c/Index.h>
namespace clang {
class Type {
public:
Type();
Type(const CXType& other);
bool operator==(const Type& rhs) const;
// Returns true if this is a fundamental type like int.
bool is_fundamental() const;
// clang::Cursor is not defined so we have to return CXCursor
CXCursor get_declaration() const;
std::string get_usr() const;
std::string get_spelling() const;
Type get_canonical() const;
// Try to resolve this type and remove qualifies, ie, Foo* will become Foo
Type strip_qualifiers() const;
Type get_return_type() const;
std::vector<Type> get_arguments() const;
std::vector<Type> get_template_arguments() const;
CXType cx_type;
};
enum class VisiterResult { Break, Continue, Recurse };
class Cursor {
public:
Cursor();
Cursor(const CXCursor& other);
explicit operator bool() const;
bool operator==(const Cursor& rhs) const;
bool operator!=(const Cursor& rhs) const;
CXCursorKind get_kind() const;
Cursor get_declaration() const;
Type get_type() const;
std::string get_spelling() const;
std::string get_display_name() const;
std::string get_usr() const;
bool is_definition() const;
// If the given cursor points to a template specialization, this
// will return the cursor pointing to the template definition.
// If the given cursor is not a template specialization, this will
// just return the same cursor.
//
// This means it is always safe to call this method.
Cursor template_specialization_to_template_definition() const;
Cursor get_referenced() const;
Cursor get_canonical() const;
Cursor get_definition() const;
Cursor get_semantic_parent() const;
std::vector<Cursor> get_arguments() const;
bool is_valid_kind() const;
std::string get_type_description() const;
std::string get_comments() const;
std::string ToString() const;
template <typename TClientData>
using Visitor = VisiterResult (*)(Cursor cursor,
Cursor parent,
TClientData* client_data);
enum class VisitResult { Completed, EndedEarly };
template <typename TClientData>
VisitResult VisitChildren(Visitor<TClientData> visitor,
TClientData* client_data) const {
if (clang_visitChildren(cx_cursor,
reinterpret_cast<CXCursorVisitor>(visitor),
client_data) == 0)
return VisitResult::Completed;
return VisitResult::EndedEarly;
}
CXCursor cx_cursor;
};
} // namespace clang
#endif // CURSOR_H_

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Cursor.h" #include "../clang_cursor.h"
#include "Index.h" #include "Index.h"
#include <clang-c/Index.h> #include <clang-c/Index.h>

View File

@ -420,18 +420,18 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
// |query_name| is the name of the variable on the query type. // |query_name| is the name of the variable on the query type.
// |index_name| is the name of the variable on the index type. // |index_name| is the name of the variable on the index type.
// |type| is the type of the variable. // |type| is the type of the variable.
#define PROCESS_UPDATE_DIFF(type_id, query_name, index_name, type) \ #define PROCESS_UPDATE_DIFF(type_id, query_name, index_name, type) \
{ \ { \
/* Check for changes. */ \ /* Check for changes. */ \
std::vector<type> removed, added; \ std::vector<type> removed, added; \
auto previous = previous_id_map.ToQuery(previous_def->index_name); \ auto previous = previous_id_map.ToQuery(previous_def->index_name); \
auto current = current_id_map.ToQuery(current_def->index_name); \ auto current = current_id_map.ToQuery(current_def->index_name); \
bool did_add = \ bool did_add = \
ComputeDifferenceForUpdate(previous, current, &removed, &added); \ ComputeDifferenceForUpdate(previous, current, &removed, &added); \
if (did_add) { \ if (did_add) { \
query_name.push_back(MergeableUpdate<type_id, type>( \ query_name.push_back(MergeableUpdate<type_id, type>( \
current_id_map.ToQuery(current_def->id), added, removed)); \ current_id_map.ToQuery(current_def->id), added, removed)); \
} \ } \
} }
// File // File
files_def_update.push_back(BuildFileDef(current_id_map, current_file)); files_def_update.push_back(BuildFileDef(current_id_map, current_file));