static void PrintCursor(CXCursor Cursor) { if (clang_isInvalid(Cursor.kind)) { CXString ks = clang_getCursorKindSpelling(Cursor.kind); printf("Invalid Cursor => %s", clang_getCString(ks)); clang_disposeString(ks); } else { CXString string, ks; CXCursor Referenced; unsigned line, column; ks = clang_getCursorKindSpelling(Cursor.kind); string = clang_getCursorSpelling(Cursor); printf("%s=%s", clang_getCString(ks), clang_getCString(string)); clang_disposeString(ks); clang_disposeString(string); Referenced = clang_getCursorReferenced(Cursor); if (!clang_equalCursors(Referenced, clang_getNullCursor())) { CXSourceLocation Loc = clang_getCursorLocation(Referenced); clang_getInstantiationLocation(Loc, 0, &line, &column, 0); printf(":%d:%d", line, column); } if (clang_isCursorDefinition(Cursor)) printf(" (Definition)"); } }
String CursorInfo::kindSpelling(uint16_t kind) { if (kind >= Invalid) { return rKindNames[kind - Invalid]; } return RTags::eatString(clang_getCursorKindSpelling(static_cast<CXCursorKind>(kind))); }
String CursorInfo::toString(unsigned cursorInfoFlags, unsigned keyFlags) const { String ret = String::format<1024>("SymbolName: %s\n" "Kind: %s\n" "Type: %s\n" "SymbolLength: %u\n" "%s" // range "%s" // enumValue "%s", // definition symbolName.constData(), RTags::eatString(clang_getCursorKindSpelling(kind)).constData(), RTags::eatString(clang_getTypeKindSpelling(type)).constData(), symbolLength, start != -1 && end != -1 ? String::format<32>("Range: %d-%d\n", start, end).constData() : "", kind == CXCursor_EnumConstantDecl ? String::format<32>("Enum Value: %lld\n", enumValue).constData() : "", isDefinition() ? "Definition\n" : ""); if (!targets.isEmpty() && !(cursorInfoFlags & IgnoreTargets)) { ret.append("Targets:\n"); for (Set<Location>::const_iterator tit = targets.begin(); tit != targets.end(); ++tit) { const Location &l = *tit; ret.append(String::format<128>(" %s\n", l.key(keyFlags).constData())); } } if (!references.isEmpty() && !(cursorInfoFlags & IgnoreReferences)) { ret.append("References:\n"); for (Set<Location>::const_iterator rit = references.begin(); rit != references.end(); ++rit) { const Location &l = *rit; ret.append(String::format<128>(" %s\n", l.key(keyFlags).constData())); } } return ret; }
void CompletionThread::run() { mIndex = clang_createIndex(0, 1); while (true) { Request *request = 0; Dump *dump = 0; { std::unique_lock<std::mutex> lock(mMutex); while (!mShutdown && mPending.isEmpty() && !mDump) { mCondition.wait(lock); } if (mShutdown) { for (auto it = mPending.begin(); it != mPending.end(); ++it) { delete *it; } mPending.clear(); if (mDump) { std::unique_lock<std::mutex> lock(mDump->mutex); mDump->done = true; mDump->cond.notify_one(); mDump = 0; } break; } else if (mDump) { std::swap(dump, mDump); } else { assert(!mPending.isEmpty()); request = mPending.takeFirst(); } } if (dump) { std::unique_lock<std::mutex> lock(dump->mutex); Log out(&dump->string); for (SourceFile *cache = mCacheList.first(); cache; cache = cache->next) { out << cache->source << "\nhash:" << cache->unsavedHash << "lastModified:" << cache->lastModified << "translationUnit:" << cache->translationUnit << "\n"; for (Completions *completion = cache->completionsList.first(); completion; completion = completion->next) { out << " " << completion->location.key() << "\n"; for (const auto &c : completion->candidates) { out << " " << c.completion << c.signature << c.priority << c.distance << RTags::eatString(clang_getCursorKindSpelling(c.cursorKind)) << "\n"; } } } dump->done = true; dump->cond.notify_one(); } else { assert(request); process(request); delete request; } } clang_disposeIndex(mIndex); mIndex = 0; }
std::string libclang_vim::stringize_cursor_kind(CXCursor const& cursor) { CXCursorKind const kind = clang_getCursorKind(cursor); cxstring_ptr kind_name = clang_getCursorKindSpelling(kind); auto const kind_type_name = stringize_cursor_kind_type(kind); return stringize_key_value("kind", kind_name) + (kind_type_name.empty() ? std::string{} : ("'kind_type':'" + kind_type_name + "',")) + stringize_cursor_extra_info(cursor); }
enum CXChildVisitResult visitor(CXCursor cursor, CXCursor parent, CXClientData data) { enum CXCursorKind cKind = clang_getCursorKind(cursor); CXString nameString = clang_getCursorDisplayName(cursor); CXString typeString = clang_getCursorKindSpelling(cKind); printf("Name:%s, Kind:%s\n", clang_getCString(nameString), clang_getCString(typeString)); clang_disposeString(nameString); clang_disposeString(typeString); return CXChildVisit_Continue; }
void print_completion_result(CXCompletionResult *completion_result, CXClientData client_data) { FILE *file = (FILE *)client_data; CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind); fprintf(file, "%s:", clang_getCString(ks)); clang_disposeString(ks); print_completion_string(completion_result->CompletionString, file); fprintf(file, "\n"); }
static void dumpCursor(char const * const str, CXCursor cursor) { CXStringDisposer name(clang_getCursorSpelling(cursor)); CXStringDisposer spstr = clang_getCursorKindSpelling(clang_getCursorKind(cursor)); std::string tokenStr; appendCursorTokenString(cursor, tokenStr); if(tokenStr.length() > 100) { tokenStr.resize(100); tokenStr += "..."; } fprintf(sLog.mFp, "%s: %s %s %s\n", str, spstr.c_str(), name.c_str(), tokenStr.c_str()); fflush(sLog.mFp); }
void ast_json::record_kind(json_t& obj, CXCursor cursor) { // Get cursor kind CXCursorKind cursorkind = clang_getCursorKind(cursor); // Get textual representation of kind CXString kindname = clang_getCursorKindSpelling(cursorkind); std::string result = clang_getCString(kindname); // Record kind obj[node::KIND] = result; // Release memory clang_disposeString(kindname); }
std::ostream& operator<<( std::ostream &os, CXCursor cursor ) { auto spelling = clang_getCursorKindSpelling( cursor.kind ); auto morespell = clang_getCursorSpelling( cursor ); os << clang_getCString( spelling ) << ":" << clang_getCString( morespell ) << " "; clang_disposeString( spelling ); clang_disposeString( morespell ); auto refcursor = clang_getCursorReferenced( cursor ); if ( clang_equalCursors( refcursor, clang_getNullCursor() )|| clang_equalCursors( refcursor, cursor ) ) return os; return os << " [ " << refcursor << " ] "; }
void PrintTo(const Cursor &cursor, ::std::ostream*os) { if (cursor.isValid()) { ClangString cursorKindSpelling(clang_getCursorKindSpelling(cursor.kind())); *os << cursorKindSpelling.cString() << " "; auto identifier = cursor.displayName(); if (identifier.hasContent()) { *os << "\"" << identifier.constData() << "\": "; } PrintTo(cursor.sourceLocation(), os); } else { *os << "Invalid cursor!"; } }
static CXChildVisitResult visitTranslationUnit(CXCursor cursor, CXCursor parent, CXClientData client_data) { visitTranslationUnitData *data = static_cast<visitTranslationUnitData*>(client_data); CXSourceRange range = clang_getCursorExtent(cursor); CXSourceLocation startLoc = clang_getRangeStart(range); CXSourceLocation endLoc = clang_getRangeEnd(range); CXFile file; unsigned startOffset; unsigned endOffset; clang_getSpellingLocation(startLoc, &file, nullptr, nullptr, &startOffset); clang_getSpellingLocation(endLoc, &file, nullptr, nullptr, &endOffset); // Use the smallest cursor that surrounds the desired location. unsigned size = endOffset - startOffset; if(clangFilesEqual(file, data->mFile) && startOffset < data->mDesiredOffset && endOffset > data->mDesiredOffset) { if(size < data->mSize) { data->mCursor = cursor; data->mSize = size; fprintf(sLog.mFp, "GOOD:\n "); } } CXStringDisposer sp = clang_getCursorSpelling(cursor); CXStringDisposer kind = clang_getCursorKindSpelling(cursor.kind); std::string fn; if(file) { CXStringDisposer s = clang_getFileName(file); fn = s; } fprintf(sLog.mFp, "%s %s off %d size %d des offset %d file %s\n", kind.c_str(), sp.c_str(), startOffset, size, data->mDesiredOffset, fn.c_str()); DUMP_PARSE("visitTU", cursor); // clang_visitChildren(cursor, ::visitTranslationUnit, client_data); // return CXChildVisit_Continue; return CXChildVisit_Recurse; }
static void printCursor(CXCursor cursor) { CXFile file; unsigned int off, line, col; CXSourceLocation location = clang_getCursorLocation(cursor); clang_getSpellingLocation(location, &file, &line, &col, &off); CXString fileName = clang_getFileName(file); const char *fileNameCStr = clang_getCString(fileName); if (fileNameCStr) { CXSourceRange range = clang_getCursorExtent(cursor); unsigned int start, end; clang_getSpellingLocation(clang_getRangeStart(range), 0, 0, 0, &start); clang_getSpellingLocation(clang_getRangeEnd(range), 0, 0, 0, &end); printf("%s:%d:%d (%d, %d-%d) ", fileNameCStr, line, col, off, start, end); } clang_disposeString(fileName); printString("kind", clang_getCursorKindSpelling(clang_getCursorKind(cursor))); printString("display name", clang_getCursorDisplayName(cursor)); printString("usr", clang_getCursorUSR(cursor)); if (clang_isCursorDefinition(cursor)) printf("definition "); printf("\n"); }
String Symbol::kindSpelling(uint16_t kind) { return kind ? RTags::eatString(clang_getCursorKindSpelling(static_cast<CXCursorKind>(kind))) : String("<none>"); }
std::string to_string(CXCursorKind k) { return string(clang_getCursorKindSpelling(k)).str(); }
static void PrintCursor(CXCursor Cursor) { if (clang_isInvalid(Cursor.kind)) { CXString ks = clang_getCursorKindSpelling(Cursor.kind); printf("Invalid Cursor => %s", clang_getCString(ks)); clang_disposeString(ks); } else { CXString string, ks; CXCursor Referenced; unsigned line, column; CXCursor SpecializationOf; ks = clang_getCursorKindSpelling(Cursor.kind); string = clang_getCursorSpelling(Cursor); printf("%s=%s", clang_getCString(ks), clang_getCString(string)); clang_disposeString(ks); clang_disposeString(string); Referenced = clang_getCursorReferenced(Cursor); if (!clang_equalCursors(Referenced, clang_getNullCursor())) { CXSourceLocation Loc = clang_getCursorLocation(Referenced); clang_getInstantiationLocation(Loc, 0, &line, &column, 0); printf(":%d:%d", line, column); } if (clang_isCursorDefinition(Cursor)) printf(" (Definition)"); switch (clang_getCursorAvailability(Cursor)) { case CXAvailability_Available: break; case CXAvailability_Deprecated: printf(" (deprecated)"); break; case CXAvailability_NotAvailable: printf(" (unavailable)"); break; } if (Cursor.kind == CXCursor_IBOutletCollectionAttr) { CXType T = clang_getCanonicalType(clang_getIBOutletCollectionType(Cursor)); CXString S = clang_getTypeKindSpelling(T.kind); printf(" [IBOutletCollection=%s]", clang_getCString(S)); clang_disposeString(S); } if (Cursor.kind == CXCursor_CXXBaseSpecifier) { enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor); unsigned isVirtual = clang_isVirtualBase(Cursor); const char *accessStr = 0; switch (access) { case CX_CXXInvalidAccessSpecifier: accessStr = "invalid"; break; case CX_CXXPublic: accessStr = "public"; break; case CX_CXXProtected: accessStr = "protected"; break; case CX_CXXPrivate: accessStr = "private"; break; } printf(" [access=%s isVirtual=%s]", accessStr, isVirtual ? "true" : "false"); } SpecializationOf = clang_getSpecializedCursorTemplate(Cursor); if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) { CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf); CXString Name = clang_getCursorSpelling(SpecializationOf); clang_getInstantiationLocation(Loc, 0, &line, &column, 0); printf(" [Specialization of %s:%d:%d]", clang_getCString(Name), line, column); clang_disposeString(Name); } } }
String Cursor::GetKindSpelling() const { return clang_getCursorKindSpelling(cursor_.kind); }
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 CompletionThread::printCompletions(const List<Completions::Candidate> &completions, Request *request) { static List<String> cursorKindNames; // error() << request->flags << testLog(RTags::Diagnostics) << completions.size() << request->conn; List<std::shared_ptr<Output> > outputs; bool xml = false; bool elisp = false; if (request->conn) { std::shared_ptr<Output> output(new Output); output->connection = request->conn; output->xml = !(request->flags & Elisp); outputs.append(output); if (request->flags & Elisp) { elisp = true; } else { xml = true; } request->conn.reset(); } log([&xml, &elisp, &outputs](const std::shared_ptr<LogOutput> &output) { // error() << "Got a dude" << output->testLog(RTags::Diagnostics); if (output->testLog(RTags::Diagnostics)) { std::shared_ptr<Output> out(new Output); out->output = output; if (output->flags() & RTagsLogOutput::Elisp) { out->xml = false; elisp = true; } else { out->xml = true; xml = true; } outputs.append(out); } }); if (!(request->flags & Refresh) && !outputs.isEmpty()) { String xmlOut, elispOut; if (xml) { xmlOut.reserve(16384); xmlOut << String::format<128>("<?xml version=\"1.0\" encoding=\"utf-8\"?><completions location=\"%s\"><![CDATA[", request->location.key().constData()); } if (elisp) { elispOut.reserve(16384); elispOut += String::format<256>("(list 'completions (list \"%s\" (list", RTags::elispEscape(request->location.key()).constData()); } for (const auto &val : completions) { if (val.cursorKind >= cursorKindNames.size()) cursorKindNames.resize(val.cursorKind + 1); String &kind = cursorKindNames[val.cursorKind]; if (kind.isEmpty()) kind = RTags::eatString(clang_getCursorKindSpelling(val.cursorKind)); if (xml) { xmlOut += String::format<128>(" %s %s %s\n", val.completion.constData(), val.signature.constData(), kind.constData()); } if (elisp) { elispOut += String::format<128>(" (list \"%s\" \"%s\" \"%s\")", RTags::elispEscape(val.completion).constData(), RTags::elispEscape(val.signature).constData(), kind.constData()); } } if (elisp) elispOut += ")))"; if (xml) xmlOut += "]]></completions>\n"; EventLoop::mainEventLoop()->callLater([outputs, xmlOut, elispOut]() { for (auto &it : outputs) { if (it->xml) { it->send(xmlOut); } else { it->send(elispOut); } } }); } }
enum CXChildVisitResult visit_program(CXCursor cursor, CXCursor parent, CXClientData data){ json_t* program = (json_t*)data; json_t* js = NULL; enum CXChildVisitResult ret = CXChildVisit_Continue; switch (clang_getCursorKind(cursor)) { case CXCursor_FunctionDecl: case CXCursor_VarDecl: js = json_object(); json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor))); json_object_set_new(js, "display_name", render_string(clang_getCursorDisplayName(cursor))); json_object_set_new(js, "type", render_type(clang_getCursorType(cursor))); if (clang_getCursorKind(cursor) == CXCursor_FunctionDecl) { json_object_set_new(js, "argument_names", json_array()); json_object_set_new(js, "kind", json_string("function")); } else { json_object_set_new(js, "kind", json_string("variable")); } switch (clang_getCursorLinkage(cursor)) { case CXLinkage_Internal: json_object_set_new(js, "linkage", json_string("static")); break; case CXLinkage_UniqueExternal: json_object_set_new(js, "linkage", json_string("anonymous")); break; case CXLinkage_External: break; default: json_object_set_new(js, "linkage", json_string("unknown")); } clang_visitChildren(cursor, visit_object, (CXClientData)js); break; case CXCursor_StructDecl: case CXCursor_UnionDecl: js = json_object(); json_object_set_new(js, "kind", json_string(clang_getCursorKind(cursor) == CXCursor_UnionDecl ? "union" : "struct")); json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor))); json_object_set_new(js, "fields", json_array()); clang_visitChildren(cursor, visit_structure, (CXClientData)js); ret = CXChildVisit_Recurse; break; case CXCursor_EnumDecl: js = json_object(); json_object_set_new(js, "kind", json_string("enum")); json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor))); json_object_set_new(js, "values", json_array()); clang_visitChildren(cursor, visit_enum, (CXClientData)js); break; case CXCursor_TypedefDecl: js = json_object(); json_object_set_new(js, "kind", json_string("typedef")); json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor))); json_object_set_new(js, "type", render_type(clang_getTypedefDeclUnderlyingType(cursor))); ret = CXChildVisit_Recurse; break; case CXCursor_FieldDecl: break; case CXCursor_MacroDefinition: js = json_object(); json_object_set_new(js, "kind", json_string("macro")); { CXToken* tokens; unsigned ntokens, i; CXString name = clang_getCursorSpelling(cursor); char value_buf[1024] = ""; json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor))); clang_tokenize(TU, clang_getCursorExtent(cursor), &tokens, &ntokens); for (i=0; i<ntokens; i++) { CXString str = clang_getTokenSpelling(TU, tokens[i]); CXTokenKind tkind = clang_getTokenKind(tokens[i]); if (i == 0 && !strcmp(clang_getCString(name), clang_getCString(str))) { // macro name } else if (i == ntokens - 1 && tkind == CXToken_Punctuation && !strcmp("#", clang_getCString(str))) { // weird clang terminator thingy } else if (tkind == CXToken_Comment) { // comment } else { if (strlen(value_buf) > 0) { strncat(value_buf, " ", sizeof(value_buf) - strlen(value_buf) - 1); } strncat(value_buf, clang_getCString(str), sizeof(value_buf) - strlen(value_buf) - 1); } clang_disposeString(str); } clang_disposeTokens(TU, tokens, ntokens); if (strlen(value_buf) > 0) { long int intval; double dblval; char* endptr_int; char* endptr_dbl; intval = strtol(value_buf, &endptr_int, 0); dblval = strtod(value_buf, &endptr_dbl); if (endptr_int[0] == 0 || (endptr_int[1] == 0 && strchr("UuLl", endptr_int[0]) != NULL)) { json_object_set_new(js, "value", json_integer(intval)); } else if (endptr_dbl[0] == 0 || (endptr_dbl[1] == 0 && strchr("fF", endptr_dbl[0]) != NULL)) { json_object_set_new(js, "value", json_real(dblval)); } else { json_object_set_new(js, "value", json_string(value_buf)); } } } break; /* case CXCursor_PreprocessingDirective: case CXCursor_MacroExpansion: js = json_object(); json_object_set_new(js, "kind", json_string("macro")); json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor))); putstring(clang_getCursorSpelling(cursor)); putstring(clang_getCursorDisplayName(cursor)); printf("%d\n", clang_getEnumConstantDeclValue(cursor)); ret = CXChildVisit_Recurse; */ default: js = json_object(); json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor))); json_object_set_new(js, "type", render_type(clang_getCursorType(cursor))); json_object_set_new(js, "kind", json_string("wtf")); json_object_set_new(js, "wtf", render_string(clang_getCursorKindSpelling(clang_getCursorKind(cursor)))); } if (js) { json_t* str; if (!json_object_get(program, "")) json_object_set_new(program, "", json_array()); str = render_string(clang_getCursorUSR(cursor)); if (strlen(json_string_value(str)) == 0) { json_decref(str); json_array_append_new(json_object_get(program, ""), js); } else { json_object_set_with_key_new(program, render_string(clang_getCursorUSR(cursor)), js); } } return ret; }
String cursorToString(CXCursor cursor, unsigned flags) { const CXCursorKind kind = clang_getCursorKind(cursor); String ret; ret.reserve(256); ret += eatString(clang_getCursorKindSpelling(kind)); if (clang_isInvalid(kind)) return ret; switch (RTags::cursorType(kind)) { case Reference: ret += " r"; break; case Cursor: ret += " c"; break; case Other: ret += " o"; break; case Include: ret += " i"; break; } const String name = eatString(clang_getCursorDisplayName(cursor)); const String other = eatString(clang_getCursorSpelling(cursor)); if (!name.isEmpty()) ret += " " + name; if (other != name && !other.isEmpty()) ret += " " + other; if (clang_isCursorDefinition(cursor)) ret += " def"; if (flags & IncludeUSR) ret += " " + eatString(clang_getCursorUSR(cursor)); CXFile file; unsigned off, line, col; //presumedLine, presumedCol, instantiationLoc, expansionLoc; CXSourceLocation location = clang_getCursorLocation(cursor); clang_getSpellingLocation(location, &file, &line, &col, &off); // clang_getPresumedLocation(location, 0, &presumedLine, &presumedCol); // clang_getInstantiationLocation(location, 0, 0, 0, &instantiationLoc); // clang_getExpansionLocation(location, 0, 0, 0, &expansionLoc); const Str fileName(clang_getFileName(file)); if (fileName.data() && *fileName.data()) { ret += ' '; ret += fileName.data(); ret += ','; ret += String::number(off); if (flags & IncludeRange) { ret += " ("; CXSourceRange range = clang_getCursorExtent(cursor); unsigned start, end; clang_getSpellingLocation(clang_getRangeStart(range), 0, 0, 0, &start); clang_getSpellingLocation(clang_getRangeEnd(range), 0, 0, 0, &end); ret += String::number(start); ret += '-'; ret += String::number(end); ret += ')'; } // if (presumedLine != line || presumedCol != col) // ret += String::snprintf<32>("presumed: %d:%d", presumedLine, presumedCol); // if (instantiationLoc != off) // ret += String::snprintf<32>("instantiation: %d", instantiationLoc); // if (expansionLoc != off) // ret += String::snprintf<32>("expansion: %d", expansionLoc); } return ret; }
void PrintTo(CXCursorKind cursorKind, ::std::ostream *os) { ClangString cursorKindSpelling(clang_getCursorKindSpelling(cursorKind)); *os << cursorKindSpelling.cString(); }