DocumentationData TranslationUnit::GetDocsForLocationInFile( 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 DocumentationData(); CXCursor cursor = GetCursor( line, column ); if ( !CursorIsValid( cursor ) ) return DocumentationData(); // If the original cursor is a reference, then we return the documentation // for the type/method/etc. that is referenced CXCursor referenced_cursor = clang_getCursorReferenced( cursor ); if ( CursorIsValid( referenced_cursor ) ) cursor = referenced_cursor; // We always want the documentation associated with the canonical declaration CXCursor canonical_cursor = clang_getCanonicalCursor( cursor ); if ( !CursorIsValid( canonical_cursor ) ) return DocumentationData(); return DocumentationData( canonical_cursor ); }
Location TranslationUnit::GetDefinitionLocation( 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 Location(); CXCursor cursor = GetCursor( line, column ); if ( !CursorIsValid( cursor ) ) return Location(); CXCursor definition_cursor = clang_getCursorDefinition( cursor ); if ( !CursorIsValid( definition_cursor ) ) return Location(); return Location( clang_getCursorLocation( definition_cursor ) ); }
Location TranslationUnit::GetDeclarationLocationForCursor( CXCursor cursor ) { CXCursor referenced_cursor = clang_getCursorReferenced( cursor ); if ( !CursorIsValid( referenced_cursor ) ) { return Location(); } CXCursor canonical_cursor = clang_getCanonicalCursor( referenced_cursor ); if ( !CursorIsValid( canonical_cursor ) ) { return Location( clang_getCursorLocation( referenced_cursor ) ); } return Location( clang_getCursorLocation( canonical_cursor ) ); }
DocumentationData TranslationUnit::GetDocsForLocation( const Location &location, 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 DocumentationData(); } CXCursor cursor = GetCursor( location.filename_, location.line_number_, location.column_number_ ); if ( !CursorIsValid( cursor ) ) { return DocumentationData(); } return DocumentationData( cursor ); }
std::string TranslationUnit::GetEnclosingFunctionAtLocation( const std::string &filename, 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( filename, line, column ); if ( !CursorIsValid( cursor ) ) { return "Internal error: cursor not valid"; } CXCursor parent = clang_getCursorSemanticParent( cursor ); std::string parent_str = CXStringToString( clang_getCursorDisplayName( parent ) ); if ( parent_str.empty() ) { return "Unknown semantic parent"; } return parent_str; }
Location TranslationUnit::GetDefinitionLocationForCursor( CXCursor cursor ) { CXCursor definition_cursor = clang_getCursorDefinition( cursor ); if ( !CursorIsValid( definition_cursor ) ) { return Location(); } return Location( clang_getCursorLocation( definition_cursor ) ); }
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; }
Location TranslationUnit::GetDefinitionOrDeclarationLocation( const std::string &filename, 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 Location(); } CXCursor cursor = GetCursor( filename, line, column ); if ( !CursorIsValid( cursor ) ) { return Location(); } // Return the definition or the declaration of a symbol under the cursor // according to the following logic: // - if the cursor is already on the definition, return the location of the // declaration; // - otherwise, search for the definition and return its location; // - if no definition is found, return the location of the declaration. if ( clang_isCursorDefinition( cursor ) ) { return GetDeclarationLocationForCursor( cursor ); } Location location = GetDefinitionLocationForCursor( cursor ); if ( location.IsValid() ) { return location; } return GetDeclarationLocationForCursor( cursor ); }
Location TranslationUnit::GetDefinitionLocation( const std::string &filename, 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 Location(); } CXCursor cursor = GetCursor( filename, line, column ); if ( !CursorIsValid( cursor ) ) { return Location(); } return GetDefinitionLocationForCursor( cursor ); }