static CXChildVisitResult parseFunctionMember (CXCursor cursor, CXCursor parent, CXClientData clientData) { auto functionDef = static_cast<FunctionDefinition*>(clientData); auto displayName = CXStringToString(clang_getCursorDisplayName(cursor)); auto kind = clang_getCursorKind(cursor); std::map<std::string, std::string> location; getSourceLocation(cursor, functionDef->getContext(), location); // std::cerr << "function: " << displayName << " kind: " << kind << ", " << hyperloop::toJSON(location) << std::endl; switch (kind) { case CXCursor_ParmDecl: { auto argType = clang_getCursorType(cursor); auto typeValue= CXStringToString(clang_getTypeSpelling(argType)); auto encoding = CXStringToString(clang_getDeclObjCTypeEncoding(cursor)); functionDef->addArgument(displayName, argType, typeValue, encoding); break; } case CXCursor_ObjCClassRef: case CXCursor_TypeRef: case CXCursor_UnexposedAttr: case CXCursor_CompoundStmt: case CXCursor_AsmLabelAttr: case CXCursor_ConstAttr: case CXCursor_PureAttr: { break; } default: { std::cerr << "not handled, function: " << displayName << " kind: " << kind << std::endl; break; } } return CXChildVisit_Continue; }
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; }
DocumentationData::DocumentationData( const CXCursor& cursor ) : raw_comment( CXStringToString( clang_Cursor_getRawCommentText( cursor ) ) ) , brief_comment( CXStringToString( clang_Cursor_getBriefCommentText( cursor ) ) ) , canonical_type( CXStringToString( clang_getTypeSpelling( clang_getCursorType( cursor ) ) ) ) , display_name( CXStringToString( clang_getCursorSpelling( cursor ) ) ) { CXComment parsed_comment = clang_Cursor_getParsedComment( cursor ); if ( CXCommentValid( parsed_comment ) ) { comment_xml = CXStringToString( clang_FullComment_getAsXML( parsed_comment ) ); } }
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; }
Diagnostic DiagnosticWrapToDiagnostic( DiagnosticWrap diagnostic_wrap ) { Diagnostic diagnostic; if ( !diagnostic_wrap ) return diagnostic; diagnostic.kind_ = DiagnosticSeverityToType( clang_getDiagnosticSeverity( diagnostic_wrap.get() ) ); // If this is an "ignored" diagnostic, there's no point in continuing since we // won't display those to the user if ( diagnostic.kind_ == 'I' ) return diagnostic; CXSourceLocation location = clang_getDiagnosticLocation( diagnostic_wrap.get() ); CXFile file; uint unused_offset; clang_getSpellingLocation( location, &file, &diagnostic.line_number_, &diagnostic.column_number_, &unused_offset ); diagnostic.filename_ = CXFileToFilepath( file ); diagnostic.text_ = CXStringToString( clang_getDiagnosticSpelling( diagnostic_wrap.get() ) ); diagnostic.long_formatted_text_ = FullDiagnosticText( diagnostic_wrap.get() ); return diagnostic; }
CompletionData::CompletionData( CXCompletionString completion_string, CXCursorKind kind, CXCodeCompleteResults *results, size_t index ) { size_t num_chunks = clang_getNumCompletionChunks( completion_string ); bool saw_left_paren = false; bool saw_function_params = false; bool saw_placeholder = false; for ( size_t j = 0; j < num_chunks; ++j ) { ExtractDataFromChunk( completion_string, j, saw_left_paren, saw_function_params, saw_placeholder ); } original_string_ = RemoveTrailingParens( std::move( original_string_ ) ); kind_ = CursorKindToCompletionKind( kind ); detailed_info_.append( return_type_ ) .append( " " ) .append( everything_except_return_type_ ) .append( "\n" ); doc_string_ = CXStringToString( clang_getCompletionBriefComment( completion_string ) ); BuildCompletionFixIt( results, index ); }
Diagnostic BuildDiagnostic( DiagnosticWrap diagnostic_wrap, CXTranslationUnit translation_unit ) { Diagnostic diagnostic; if ( !diagnostic_wrap ) return diagnostic; diagnostic.kind_ = DiagnosticSeverityToType( clang_getDiagnosticSeverity( diagnostic_wrap.get() ) ); // If this is an "ignored" diagnostic, there's no point in continuing since we // won't display those to the user if ( diagnostic.kind_ == INFORMATION ) return diagnostic; CXSourceLocation source_location = clang_getDiagnosticLocation( diagnostic_wrap.get() ); diagnostic.location_ = Location( source_location ); diagnostic.location_extent_ = GetLocationExtent( source_location, translation_unit ); diagnostic.ranges_ = GetRanges( diagnostic_wrap ); diagnostic.text_ = CXStringToString( clang_getDiagnosticSpelling( diagnostic_wrap.get() ) ); diagnostic.long_formatted_text_ = FullDiagnosticText( diagnostic_wrap.get() ); return diagnostic; }
CXChildVisitResult FunctionDefinition::executeParse (CXCursor cursor, ParserContext *context) { auto returnType = clang_getCursorResultType(cursor); auto returnTypeValue = CXStringToString(clang_getTypeSpelling(clang_getCursorResultType(cursor))); this->returnType = new Type(context, returnType, returnTypeValue); this->variadic = clang_isFunctionTypeVariadic(clang_getCursorType(cursor)); addBlockIfFound(context, this, this->getFramework(), this->returnType, ""); context->getParserTree()->addFunction(this); clang_visitChildren(cursor, parseFunctionMember, this); return CXChildVisit_Continue; }
CompilationInfoForFile CompilationDatabase::GetCompilationInfoForFile( const std::string &path_to_file ) { ReleaseGil unlock; CompilationInfoForFile info; if ( !is_loaded_ ) return info; lock_guard< mutex > lock( compilation_database_mutex_ ); CompileCommandsWrap commands( clang_CompilationDatabase_getCompileCommands( compilation_database_, path_to_file.c_str() ), clang_CompileCommands_dispose ); uint num_commands = clang_CompileCommands_getSize( commands.get() ); if ( num_commands < 1 ) { return info; } // We always pick the first command offered CXCompileCommand command = clang_CompileCommands_getCommand( commands.get(), 0 ); info.compiler_working_dir_ = CXStringToString( clang_CompileCommand_getDirectory( command ) ); uint num_flags = clang_CompileCommand_getNumArgs( command ); info.compiler_flags_.reserve( num_flags ); for ( uint i = 0; i < num_flags; ++i ) { info.compiler_flags_.push_back( CXStringToString( clang_CompileCommand_getArg( command, i ) ) ); } return info; }
void CompletionData::BuildCompletionFixIt( CXCodeCompleteResults *results, size_t index ) { size_t num_chunks = clang_getCompletionNumFixIts( results, index ); if ( !num_chunks ) { return; } fixit_.chunks.reserve( num_chunks ); for ( size_t chunk_index = 0; chunk_index < num_chunks; ++chunk_index ) { FixItChunk chunk; CXSourceRange range; chunk.replacement_text = CXStringToString( clang_getCompletionFixIt( results, index, chunk_index, &range ) ); chunk.range = range; fixit_.chunks.push_back( chunk ); } }
std::string ClangVersion() { return CXStringToString( clang_getClangVersion() ); }
std::string CXFileToFilepath( CXFile file ) { return CXStringToString( clang_getFileName( file ) ); }