std::string TranslationUnit::GetTypeAtLocation( int line, int column, const std::vector< UnsavedFile > &unsaved_files, bool reparse ) { if ( reparse ) Reparse( unsaved_files ); unique_lock< mutex > lock( clang_access_mutex_ ); if ( !clang_translation_unit_ ) return "Internal error: no translation unit"; CXCursor cursor = GetCursor( line, column ); if ( !CursorIsValid( cursor ) ) return "Internal error: cursor not valid"; CXType type = clang_getCursorType( cursor ); std::string type_description = CXStringToString( clang_getTypeSpelling( type ) ); if ( type_description.empty() ) return "Unknown type"; // We have a choice here; libClang provides clang_getCanonicalType which will // return the "underlying" type for the type returned by clang_getCursorType // e.g. for a typedef // type = clang_getCanonicalType( type ); // // Without the above, something like the following would return "MyType" // rather than int: // typedef int MyType; // MyType i = 100; <-- type = MyType, canonical type = int // // There is probably more semantic value in calling it MyType. Indeed, if we // opt for the more specific type, we can get very long or // confusing STL types even for simple usage. e.g. the following: // std::string test = "test"; <-- type = std::string; // canonical type = std::basic_string<char> // // So as a compromise, we return both if and only if the types differ, like // std::string => std::basic_string<char> CXType canonical_type = clang_getCanonicalType( type ); if ( !clang_equalTypes( type, canonical_type ) ) { type_description += " => "; type_description += CXStringToString( clang_getTypeSpelling( canonical_type ) ); } return type_description; }
MetadataEnum::Ptr MetadataModule::FindEnumByType(CXType type) { for (auto& ptr : Enums) { if (clang_equalTypes(ptr->ClangType, type)) { return ptr; } } return nullptr; }
MetadataClass::Ptr MetadataModule::FindClassByType(CXType type) { for (auto& ptr : Classes) { if (clang_equalTypes(ptr->ClangType, type)) { return ptr; } } return nullptr; }
std::string translation_unit::type_at(uint32_t row, uint32_t col) { CXCursor cursor = get_cursor_at(row, col); if (clang_Cursor_isNull(cursor) || clang_isInvalid(clang_getCursorKind(cursor))) return ""; CXType type = clang_getCursorType(cursor); CXType real_type = clang_getCanonicalType( type ); std::string ret = cx2std(clang_getTypeSpelling(type)); if (!clang_equalTypes(type, real_type)) { ret.append(" - "); ret.append(cx2std(clang_getTypeSpelling(real_type))); } return ret; }
bool cursor::type::operator==(const type& o) { return clang_equalTypes(ctype, o.ctype); }
bool operator==(Type first, Type second) { return clang_equalTypes(first.m_cxType, second.m_cxType); }