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; }
std::ostream& operator<<( std::ostream& os, CXType type ) { auto typestr = clang_getTypeSpelling( type ); os << "Type: " << clang_getCString( typestr ) << "\n"; clang_disposeString( typestr ); return os; }
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 libclang_vim::stringize_type(CXType const& type) { CXTypeKind const type_kind = type.kind; cxstring_ptr type_name = clang_getTypeSpelling(type); cxstring_ptr type_kind_name = clang_getTypeKindSpelling(type_kind); return stringize_key_value("type", type_name) + stringize_key_value("type_kind", type_kind_name) + stringize_extra_type_info(type); }
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; }
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; }
QASTField::QASTField( QAnnotatedTokenSet *tokenSet, QSourceLocation* cursorLocation, QSourceLocation* rangeStartLocation, QSourceLocation* rangeEndLocation, QASTNode* parent) : QASTNode("field", tokenSet, cursorLocation, rangeStartLocation, rangeEndLocation, parent){ // Get Identifier // -------------- CXString id = clang_getCursorSpelling(tokenSet->cursor()); setIdentifier(clang_getCString(id)); // Get Field Type // --------------- CXType type = clang_getCursorType(tokenSet->cursor()); CXString typeSpelling = clang_getTypeSpelling(type); m_fieldType = clang_getCString(typeSpelling); clang_disposeString(typeSpelling); // Determine field type // -------------------- if ( type.kind == CXType_Unexposed || type.kind == CXType_Invalid || m_fieldType.contains("int") ){ m_fieldType = ""; bool doubleColonFlag = false; for ( QAnnotatedTokenSet::Iterator it = tokenSet->begin(); it != tokenSet->end(); ++it ){ CXToken t = (*it)->token().token; CXString tSpelling = clang_getTokenSpelling(tokenSet->translationUnit(), t); const char* tCSpelling = clang_getCString(tSpelling); CXTokenKind tKind = clang_getTokenKind(t); if ( tKind == CXToken_Identifier && std::string(clang_getCString(id)) == tCSpelling ){ break; } else if ( tKind == CXToken_Punctuation && std::string("::") == tCSpelling ){ doubleColonFlag = true; m_fieldType += tCSpelling; } else if ( ( tKind == CXToken_Identifier || tKind == CXToken_Keyword ) && !m_fieldType.isEmpty() && !doubleColonFlag ){ m_fieldType += QString(" ") + tCSpelling; } else { doubleColonFlag = false; m_fieldType += tCSpelling; } } } clang_disposeString(id); }
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 ) ); } }
static enum CXChildVisitResult visitor_struct_cb(CXCursor cursor, CXCursor parent, CXClientData client_data) { ERL_NIF_TERM name; ERL_NIF_TERM typename; CXString tmp; CXType type; ERL_NIF_TERM etmp; unsigned len; SubData *data = (SubData*)client_data; ErlNifEnv *env = data->env; switch (clang_getCursorKind(cursor)) { case CXCursor_FieldDecl: { enif_get_list_length(env, data->data, &len); tmp = clang_getCursorSpelling(cursor); name = enif_make_string(env, clang_getCString(tmp), ERL_NIF_LATIN1); clang_disposeString(tmp); type = clang_getCursorType(cursor); tmp = clang_getTypeSpelling(type); typename = enif_make_string(env, clang_getCString(tmp), ERL_NIF_LATIN1); data->types = enif_make_list_cell(env, typename, data->types); clang_disposeString(tmp); etmp = enif_make_tuple4(env, enif_make_atom(env, "field"), name, typename, enif_make_uint(env, len)); data->data = enif_make_list_cell(env, etmp, data->data); return CXChildVisit_Continue; } default: { return CXChildVisit_Continue; } } }
void Irony::getType(unsigned line, unsigned col) const { if (activeTu_ == nullptr) { std::clog << "W: get-type - parse wasn't called\n"; std::cout << "nil\n"; return; } CXFile cxFile = clang_getFile(activeTu_, file_.c_str()); CXSourceLocation sourceLoc = clang_getLocation(activeTu_, cxFile, line, col); CXCursor cursor = clang_getCursor(activeTu_, sourceLoc); if (clang_Cursor_isNull(cursor)) { // TODO: "error: no type at point"? std::cout << "nil"; return; } CXType cxTypes[2]; cxTypes[0] = clang_getCursorType(cursor); cxTypes[1] = clang_getCanonicalType(cxTypes[0]); std::cout << "("; for (const CXType &cxType : cxTypes) { CXString typeDescr = clang_getTypeSpelling(cxType); std::string typeStr = clang_getCString(typeDescr); clang_disposeString(typeDescr); if (typeStr.empty()) break; std::cout << support::quoted(typeStr) << " "; } std::cout << ")\n"; }
bool Type::Build(const CXType &cxType) { bool result = true; auto arraySize = clang_getArraySize(cxType); m_ArraySize = arraySize > 0 ? static_cast<int>(arraySize) : 0; int numTemplateArgs = clang_Type_getNumTemplateArguments(cxType); for (int i = 0; i < numTemplateArgs; ++i) { CXType tempType = clang_Type_getTemplateArgumentAsType(cxType, static_cast<unsigned>(i)); const char *tempTypeSpelling = clang_getCString(clang_getTypeSpelling(tempType)); std::unique_ptr<Type> t = std::unique_ptr<Type>(CreateFromString(this, tempTypeSpelling)); if (t->Build(tempType)) { m_TemplateArgs.push_back(std::move(t)); } else result = false; } return result; }
std::string cursor::type::spelling() { return string(clang_getTypeSpelling(ctype)).str(); }
enum CXChildVisitResult visitor( CXCursor cursor, CXCursor parent, CXClientData client_data ) { enum CXCursorKind kind = clang_getCursorKind(cursor); #if 0 CXString str = clang_getCursorKindSpelling(kind); printf("%s\n", getCString(str)); disposeString(str); #endif if (kind != CXCursor_FunctionDecl) { return CXChildVisit_Recurse; } CXString str; CXType retType = clang_getCursorResultType(cursor); str = clang_getTypeSpelling(retType); printf("%s\n", clang_getCString(str)); clang_disposeString(str); CXString funcSpelling = clang_getCursorSpelling(cursor); const char* funcSpellingCStr = clang_getCString(funcSpelling); const char* prefix = (const char*) client_data; size_t prefixLen = strlen(prefix); if (strncmp(prefix, funcSpellingCStr, prefixLen) == 0) { funcSpellingCStr += prefixLen; } printf("\t%s(\n", funcSpellingCStr); int nArgs = clang_Cursor_getNumArguments(cursor); argNames.resize(nArgs); char nameBuff[32]; for (int i=0; i<nArgs; ++i) { CXCursor arg = clang_Cursor_getArgument(cursor, i); CXType type = clang_getCursorType(arg); CXString typeSpelling = clang_getTypeSpelling(type); CXString name = clang_getCursorDisplayName(arg); argNames[i] = name; const char* nameStr = getArgNameCString(nameBuff, name, i); printf("\t\t%s %s", clang_getCString(typeSpelling), nameStr); clang_disposeString(typeSpelling); if (i+1 != nArgs) { printf(","); } printf("\n"); } printf("\t)\n"); printf("{\n"); printf("\t"); if (retType.kind != CXType_Void) { printf("return "); } printf("%s(", funcSpelling); for (int i=0; i<nArgs; ++i) { const char* nameStr = getArgNameCString(nameBuff, argNames[i], i); printf("%s", nameStr); if (i+1 != nArgs) { printf(", "); } clang_disposeString(argNames[i]); } printf(");\n"); printf("}\n"); clang_disposeString(funcSpelling); return CXChildVisit_Continue; }
void TokenizeSource(CXTranslationUnit tu) { CXSourceRange range = clang_getCursorExtent( clang_getTranslationUnitCursor(tu) ); CXToken *tokens; unsigned int token_count; clang_tokenize( tu, range, &tokens, &token_count ); //CXCursor cursors[ token_count ]; //clang_annotateTokens( tu, tokens, token_count, cursors ); auto cursors = my_annotateTokens( tu, tokens, token_count ); for ( auto t = 0u; t < token_count; ++t ) { auto tkind = clang_getTokenKind(tokens[t] ); auto tspelling = tkind == CXToken_Identifier ? CursorKindSpelling( cursors[ t ] ) : TokenKindSpelling( tkind ); auto textent = clang_getTokenExtent( tu, tokens[t] ); auto tstartloc = clang_getRangeStart( textent ); auto tendloc = clang_getRangeEnd( textent ); auto tokspell = clang_getTokenSpelling( tu, tokens[ t ] ); std::cout << "TokenSpelling: " << tokspell << "\n"; std::cout << "Cursor: " << cursors[ t ] << "\n"; // if ( !( cursors[t].kind >= CXCursor_FirstInvalid && // cursors[t].kind <= CXCursor_LastInvalid ) ) { // auto rr = clang_getCursorExtent( cursors[ t ] ); // std::cout << "Range: " << rr << "\n"; // } // std::cout << clang_getCursorDisplayName( cursors[ t ] ) << "\n"; // std::cout << "USR: "******"\n"; unsigned int startoffset, endoffset; clang_getSpellingLocation( tstartloc, nullptr, nullptr, nullptr, &startoffset ); clang_getSpellingLocation( tendloc, nullptr, nullptr, nullptr, &endoffset ); // TODO: testing this hack for int -> identifier instead of keyword // but this loses const to an identifier also! fvck! if ( tspelling == "Keyword" ) { auto type = clang_getCursorType( cursors[ t ] ); auto typekind = type.kind; CXString typespelling; if ( cursors[t].kind == CXCursor_FunctionDecl || cursors[t].kind == CXCursor_CXXMethod ) { type = clang_getResultType( type ); typekind = type.kind; typespelling = clang_getTypeSpelling( type ); } else typespelling = clang_getTypeSpelling( type ); // std::cout << "Type = " << type << " kind: " << typekind << "\n"; // std::cout << clang_getCString(typespelling) << " <-> " << clang_getCString(tokspell) << "\n"; // std::cout << " Const? " << clang_isConstQualifiedType( type ) << "\n"; if ( (( typekind >= CXType_FirstBuiltin && typekind <= CXType_LastBuiltin ) && ( std::string(clang_getCString(typespelling)) == std::string(clang_getCString(tokspell) ) )) || // ( cursors[t].kind == CXCursor_VarDecl ) || ( cursors[t].kind == CXCursor_ParmDecl ) ) tspelling = "Identifier"; } //if ( tspelling != "Punctuation" ) std::cout << startoffset << ":" << endoffset << " @ " << tspelling << "\n"; clang_disposeString( tokspell ); } std::cout << "\n" << end_pattern << "\n"; clang_disposeTokens( tu, tokens, token_count ); }
String Type::GetSpelling() const { return clang_getTypeSpelling(type_); }
Utf8String Type::utf8Spelling() const { return ClangString(clang_getTypeSpelling(m_cxType)); }