void ast_json::record_extent(json_t& obj, CXSourceRange extent) { CXSourceLocation startlocation = clang_getRangeStart( extent ); CXSourceLocation endlocation = clang_getRangeEnd( extent ); // Get exact source locations unsigned int startline = 0, startcolumn = 0, startoffset = 0; unsigned int endline = 0, endcolumn = 0, endoffset = 0; clang_getSpellingLocation( startlocation, nullptr, &startline, &startcolumn, &startoffset ); clang_getSpellingLocation( endlocation, nullptr, &endline, &endcolumn, &endoffset ); // Record source location obj[node::START_LINE] = startline; obj[node::START_COLUMN] = startcolumn; obj[node::START_OFFSET] = startoffset; obj[node::END_LINE] = endline; obj[node::END_COLUMN] = endcolumn; obj[node::END_OFFSET] = endoffset; }
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; }
static CXCursor getCursorUsingTokens(CXTranslationUnit tu, CXCursor cursor, unsigned int desiredOffset) { // The following does not return a more definitive cursor. // For example, if a compound statement is returned, this does not find // any variables in the statement. CXSourceRange range = clang_getCursorExtent(cursor); CXToken *tokens; unsigned numTokens; clang_tokenize(tu, range, &tokens, &numTokens); unsigned int closestOffset = 0; for(unsigned int i=0; i<numTokens; i++) { CXSourceLocation loc = clang_getTokenLocation(tu, tokens[i]); unsigned int offset; CXFile file; clang_getSpellingLocation(loc, &file, nullptr, nullptr, &offset); if(offset < desiredOffset && offset > closestOffset) { closestOffset = offset; cursor = clang_getCursor(tu, loc); } } clang_disposeTokens(tu, tokens, numTokens); return cursor; }
void IndexerJob::inclusionVisitor(CXFile includedFile, CXSourceLocation *includeStack, unsigned includeLen, CXClientData userData) { IndexerJob *job = static_cast<IndexerJob*>(userData); const Location l(includedFile, 0); const Path path = l.path(); job->mData->symbolNames[path].insert(l); const char *fn = path.fileName(); job->mData->symbolNames[String(fn, strlen(fn))].insert(l); const uint32_t fileId = l.fileId(); if (!includeLen) { job->mData->dependencies[fileId].insert(fileId); } else { for (unsigned i=0; i<includeLen; ++i) { CXFile originatingFile; clang_getSpellingLocation(includeStack[i], &originatingFile, 0, 0, 0); Location loc(originatingFile, 0); const uint32_t f = loc.fileId(); if (f) job->mData->dependencies[fileId].insert(f); } } }
string CursorHelper::getFileName(CXCursor cursor) { CXFile file; clang_getSpellingLocation(clang_getCursorLocation(cursor), &file, 0, 0, 0); CXString fileStr = clang_getFileName(file); string fileName(clang_getCString(fileStr)); clang_disposeString(fileStr); return fileName; }
void ClangIndexer::superclassTemplateMemberFunctionUgleHack(const CXCursor &cursor, CXCursorKind kind, const Location &location, const CXCursor &ref, const CXCursor &parent) { // This is for references to superclass template functions. Awful awful // shit. See https://github.com/Andersbakken/rtags/issues/62 and commit // for details. I really should report this as a bug. if (kind == CXCursor_MemberRefExpr && clang_getCursorKind(parent) == CXCursor_CallExpr) { const CXCursor templateRef = RTags::findChild(cursor, CXCursor_TemplateRef); if (templateRef == CXCursor_TemplateRef) { const CXCursor classTemplate = clang_getCursorReferenced(templateRef); if (classTemplate == CXCursor_ClassTemplate) { FILE *f = fopen(location.path().constData(), "r"); if (f) { const CXSourceRange range = clang_getCursorExtent(cursor); const CXSourceLocation end = clang_getRangeEnd(range); unsigned offset; clang_getSpellingLocation(end, 0, 0, 0, &offset); String name; while (offset > 0) { fseek(f, --offset, SEEK_SET); char ch = static_cast<char>(fgetc(f)); if (isalnum(ch) || ch == '_' || ch == '~') { name.prepend(ch); } else { break; } } fclose(f); if (!name.isEmpty()) { RTags::Filter out; out.kinds.insert(CXCursor_MemberRefExpr); const int argCount = RTags::children(parent, RTags::Filter(), out).size(); RTags::Filter in(RTags::Filter::And); in.names.insert(name); in.argumentCount = argCount; const List<CXCursor> alternatives = RTags::children(classTemplate, in); switch (alternatives.size()) { case 1: // ### not sure this is correct with line/col handleReference(cursor, kind, Location(location.fileId(), location.line(), location.column() + 1), alternatives.first(), parent); break; case 0: break; default: warning() << "Can't decide which of these cursors are right for me" << cursor << alternatives << "Need to parse types"; break; } } } } } } }
/** * CXSourceLocation - 4-byte number, we need to call clang_getSpellingLocation * or clang_getExpansionLocation to retrieve line, column and file name. */ void Generator::getLocationParts(const CXSourceLocation &location, std::string &fileName, unsigned &line, unsigned &column) const { CXFile file; unsigned offset = 0; clang_getSpellingLocation(location, &file, &line, &column, &offset); (void)offset; fileName = stringize(clang_getFileName(file)); }
int ClangParser::Private::getCurrentTokenLine() { uint l, c; if (numTokens==0) return 1; // guard against filters that reduce the number of lines if (curToken>=numTokens) curToken=numTokens-1; CXSourceLocation start = clang_getTokenLocation(tu,tokens[curToken]); clang_getSpellingLocation(start, 0, &l, &c, 0); return l; }
std::string libclang_vim::stringize_location(CXSourceLocation const& location) { CXFile file; unsigned int line, column, offset; clang_getSpellingLocation(location, &file, &line, &column, &offset); cxstring_ptr file_name = clang_getFileName(file); return "'line':" + std::to_string(line) + ",'column':" + std::to_string(column) + ",'offset':" + std::to_string(offset) + ',' + stringize_key_value("file", file_name); }
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; }
Location IndexerJob::createLocation(const CXCursor &cursor) { CXSourceLocation location = clang_getCursorLocation(cursor); if (!clang_equalLocations(location, nullLocation)) { CXFile file; unsigned start; clang_getSpellingLocation(location, &file, 0, 0, &start); if (file) { return Location(file, start); } } return Location(); }
/** * CXSourceLocation - 4-байтное число, для извлечения имени файла и позиции в * файле потребуется один из вызовов clang_getSpellingLocation или * clang_getExpansionLocation */ void decodeLocation(const CXSourceLocation &location, std::string &fileName, unsigned &line, unsigned &column) { CXFile file; unsigned offset; clang_getSpellingLocation(location, &file, &line, &column, &offset); (void)offset; CXString cxName = clang_getFileName(file); fileName = clang_getCString(cxName); clang_disposeString(cxName); }
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"); }
void ClangUtils::GetCursorLocation(CXCursor cursor, wxString& filename, unsigned& line, unsigned& col) { CXSourceLocation loc = clang_getCursorLocation(cursor); CXFile file; unsigned off; line = 1, col = 1; clang_getSpellingLocation(loc, &file, &line, &col, &off); CXString strFileName = clang_getFileName(file); filename = wxString(clang_getCString(strFileName), wxConvUTF8); clang_disposeString(strFileName); }
location::location(const CXSourceLocation loc) { CXFile file; unsigned line; unsigned column; unsigned offset; clang_getSpellingLocation(loc, &file, &line, &column, &offset); if (file == nullptr) throw exception::invalid("No file has attached to a source location"); DCXString filename = {clang_getFileName(static_cast<CXFile>(file))}; m_file = clang_getCString(filename); assert("Sanity check" && m_file.isValid() && !m_file.isEmpty()); m_file.cleanPath(); m_line = line; m_column = column; m_offset = offset; }
bool filterByFilename(CXCursor cu) { // hardcoded to exclude anything from '/usr/include' - todo: take a list of paths to accept/ reject bool ret=true; CXSourceLocation srcLoc = clang_getCursorLocation(cu); CXFile file; clang_getSpellingLocation(srcLoc,&file,0,0,0); CXString filename = clang_getFileName(file); const char* szfilename=clang_getCString(filename); const char* exclude_path="/usr/include"; if (szfilename) { const char* s1=szfilename,*s2=exclude_path; while (*s1 && *s2) { if (*s1!=*s2) break; s1++,s2++; } if (!*s2) ret=false; if (!ret) {printf("filtered out %s\n", szfilename);} } clang_disposeString(filename); return ret; }
CXChildVisitResult visitor( CXCursor cursor, CXCursor parent, CXClientData d ) { auto range = clang_getCursorExtent( cursor ); auto space = reinterpret_cast<int>( d ); if ( space > 0 ) std::cout << std::setw( space ) << " "; std::cout << cursor << " " << range << "\n"; space += 2; auto location = clang_getCursorLocation( cursor ); CXFile thisfile; clang_getSpellingLocation( location, &thisfile, NULL, NULL, NULL ); if ( cursor.kind != CXCursor_InclusionDirective && clang_getFile( tu, filename.c_str() ) == thisfile ) clang_visitChildren( cursor, visitor, reinterpret_cast<CXClientData>(space) ); return CXChildVisit_Continue; }
void QAnnotatedTokenSet::dump(std::string &str){ Q_D(QAnnotatedTokenSet); CXString displayName = clang_getCursorDisplayName(d->cursor); str.append("Cursor :"); str.append(clang_getCString(displayName)); str.append("\n Tokens :"); clang_disposeString(displayName); for ( QAnnotatedTokenSet::Iterator it = begin(); it != end(); ++it ){ CXString tokenString = clang_getTokenSpelling(d->translationUnit, (*it)->token().token); CXSourceLocation tokenLocation = clang_getTokenLocation(d->translationUnit, (*it)->token().token); unsigned int column, line; clang_getSpellingLocation(tokenLocation, 0, &line, &column, 0); std::stringstream stream; stream << " (" << line << "," << column << ") \""; str.append(stream.str() + clang_getCString(tokenString) + "\""); clang_disposeString(tokenString); } str.append("\n"); }
void ClangIndexer::inclusionVisitor(CXFile includedFile, CXSourceLocation *includeStack, unsigned includeLen, CXClientData userData) { ClangIndexer *indexer = static_cast<ClangIndexer*>(userData); const Location l = indexer->createLocation(includedFile, 1, 1); const uint32_t fileId = l.fileId(); if (!includeLen) { indexer->mData->dependencies[fileId].insert(fileId); } else { for (unsigned i=0; i<includeLen; ++i) { CXFile originatingFile; clang_getSpellingLocation(includeStack[i], &originatingFile, 0, 0, 0); const Location loc = indexer->createLocation(originatingFile, 1, 1); const uint32_t f = loc.fileId(); if (f) indexer->mData->dependencies[fileId].insert(f); } } }
Location IndexerJob::createLocation(const CXSourceLocation &location, bool *blocked) { Location ret; if (blocked) *blocked = false; if (!clang_equalLocations(location, nullLocation)) { CXFile file; unsigned start; clang_getSpellingLocation(location, &file, 0, 0, &start); if (file) { String fileName = RTags::eatString(clang_getFileName(file)); uint32_t &fileId = mFileIds[fileName]; if (!fileId) fileId = Location::insertFile(Path::resolved(fileName)); ret = Location(fileId, start); if (blocked) { if (mVisitedFiles.contains(fileId)) { *blocked = false; } else if (mBlockedFiles.contains(fileId)) { *blocked = true; ret.clear(); } else { shared_ptr<Project> p = project(); const bool ok = p && p->visitFile(fileId); *blocked = !ok; if (!ok) { ret.clear(); mBlockedFiles.insert(fileId); } else { mVisitedFiles.insert(fileId); } } } } } return ret; }
string CursorHelper::getColumnNumber(CXCursor cursor) { unsigned column; clang_getSpellingLocation(clang_getCursorLocation(cursor), 0, 0, &column, 0); return itoa(column); }
bool IndexerJob::diagnose(int build, int *errorCount) { if (errorCount) *errorCount = 0; if (!mUnits.at(build).second) { abort(); return false; } List<String> compilationErrors; const unsigned diagnosticCount = clang_getNumDiagnostics(mUnits.at(build).second); const unsigned options = Server::instance()->options().options; for (unsigned i=0; i<diagnosticCount; ++i) { CXDiagnostic diagnostic = clang_getDiagnostic(mUnits.at(build).second, i); int logLevel = INT_MAX; const CXDiagnosticSeverity severity = clang_getDiagnosticSeverity(diagnostic); switch (severity) { case CXDiagnostic_Fatal: case CXDiagnostic_Error: if (errorCount) ++*errorCount; logLevel = Error; break; case CXDiagnostic_Warning: logLevel = Warning; break; case CXDiagnostic_Note: logLevel = Debug; break; case CXDiagnostic_Ignored: break; } const unsigned diagnosticOptions = (CXDiagnostic_DisplaySourceLocation| CXDiagnostic_DisplayColumn| CXDiagnostic_DisplaySourceRanges| CXDiagnostic_DisplayOption| CXDiagnostic_DisplayCategoryId| CXDiagnostic_DisplayCategoryName); const uint32_t fileId = createLocation(clang_getDiagnosticLocation(diagnostic), 0).fileId(); if (mVisitedFiles.contains(fileId)) { const String text = RTags::eatString(clang_formatDiagnostic(diagnostic, diagnosticOptions)); if (testLog(logLevel) || testLog(CompilationError)) { log(logLevel, "%s: %s => %s", mSourceInformation.sourceFile.constData(), mClangLines.at(build).constData(), text.constData()); compilationErrors.append(text); } const unsigned fixItCount = clang_getDiagnosticNumFixIts(diagnostic); RegExp rx; if (options & Server::IgnorePrintfFixits) { rx = "^%[A-Za-z0-9]\\+$"; } for (unsigned f=0; f<fixItCount; ++f) { CXSourceRange range; const String string = RTags::eatString(clang_getDiagnosticFixIt(diagnostic, f, &range)); unsigned startOffset; CXFile file; clang_getSpellingLocation(clang_getRangeStart(range), &file, 0, 0, &startOffset); unsigned endOffset; clang_getSpellingLocation(clang_getRangeEnd(range), 0, 0, 0, &endOffset); const Location loc(file, startOffset); if (options & Server::IgnorePrintfFixits && rx.indexIn(string) == 0) { error("Ignored fixit for %s: Replace %d-%d with [%s]", loc.path().constData(), startOffset, endOffset, string.constData()); } else { error("Fixit for %s: Replace %d-%d with [%s]", loc.path().constData(), startOffset, endOffset, string.constData()); compilationErrors.append(String::format<128>("Fixit for %s: Replace %d-%d with [%s]", loc.path().constData(), startOffset, endOffset, string.constData())); mData->fixIts[loc.fileId()].insert(FixIt(startOffset, endOffset, string)); } } } clang_disposeDiagnostic(diagnostic); } if (testLog(CompilationError)) sendDiagnostics(compilationErrors); return !isAborted(); }
bool IndexerJob::handleCursor(const CXCursor &cursor, CXCursorKind kind, const Location &location) { CursorInfo &info = mData->symbols[location]; if (!info.symbolLength || !RTags::isCursor(info.kind)) { CXStringScope name = clang_getCursorSpelling(cursor); const char *cstr = name.data(); info.symbolLength = cstr ? strlen(cstr) : 0; info.type = clang_getCursorType(cursor).kind; if (!info.symbolLength) { // this is for these constructs: // typedef struct { // int a; // } foobar; // // We end up not getting a spelling for the cursor switch (kind) { case CXCursor_ClassDecl: info.symbolLength = 5; info.symbolName = "class"; break; case CXCursor_UnionDecl: info.symbolLength = 5; info.symbolName = "union"; break; case CXCursor_StructDecl: info.symbolLength = 6; info.symbolName = "struct"; break; default: mData->symbols.remove(location); return false; } } else { info.symbolName = addNamePermutations(cursor, location); } 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); info.start = start; info.end = end; if (kind == CXCursor_EnumConstantDecl) { #if CLANG_VERSION_MINOR > 1 info.enumValue = clang_getEnumConstantDeclValue(cursor); #else info.definition = clang_isCursorDefinition(cursor); #endif } else{ info.definition = clang_isCursorDefinition(cursor); } info.kind = kind; const String usr = RTags::eatString(clang_getCursorUSR(cursor)); if (!usr.isEmpty()) mData->usrMap[usr].insert(location); switch (info.kind) { case CXCursor_Constructor: case CXCursor_Destructor: { Location parentLocation = createLocation(clang_getCursorSemanticParent(cursor)); // consider doing this for only declaration/inline definition since // declaration and definition should know of one another if (parentLocation.isValid()) { CursorInfo &parent = mData->symbols[parentLocation]; parent.references.insert(location); info.references.insert(parentLocation); } break; } case CXCursor_CXXMethod: { List<CursorInfo*> infos; infos.append(&info); addOverriddenCursors(cursor, location, infos); break; } default: break; } } return true; }
void IndexerJob::handleReference(const CXCursor &cursor, CXCursorKind kind, const Location &location, const CXCursor &ref, const CXCursor &parent) { const CXCursorKind refKind = clang_getCursorKind(ref); if (clang_isInvalid(refKind)) { superclassTemplateMemberFunctionUgleHack(cursor, kind, location, ref, parent); return; } bool isOperator = false; if (kind == CXCursor_CallExpr && (refKind == CXCursor_CXXMethod || refKind == CXCursor_ConversionFunction || refKind == CXCursor_FunctionDecl || refKind == CXCursor_FunctionTemplate)) { // these are bullshit, for this construct: // foo.bar(); // the position of the cursor is at the foo, not the bar. // They are not interesting for followLocation, renameSymbol or find // references so we toss them. // For functions it can be the position of the namespace. // E.g. Foo::bar(); cursor is on Foo // For constructors they happen to be the only thing we have that // actually refs the constructor and not the class so we have to keep // them for that. return; } switch (refKind) { case CXCursor_Constructor: if (isImplicit(ref)) return; break; case CXCursor_CXXMethod: case CXCursor_FunctionDecl: case CXCursor_FunctionTemplate: { CXStringScope scope = clang_getCursorDisplayName(ref); const char *data = scope.data(); if (data) { const int len = strlen(data); if (len > 8 && !strncmp(data, "operator", 8) && !isalnum(data[8]) && data[8] != '_') { if (isImplicit(ref)) return; // eat implicit operator calls isOperator = true; } } break; } default: break; } const Location reffedLoc = createLocation(ref, 0); if (!reffedLoc.isValid()) return; CursorInfo &refInfo = mData->symbols[reffedLoc]; if (!refInfo.symbolLength && !handleCursor(ref, refKind, reffedLoc)) return; refInfo.references.insert(location); CursorInfo &info = mData->symbols[location]; info.targets.insert(reffedLoc); // We need the new cursor to replace the symbolLength. This is important // in the following case: // struct R { R(const &r); ... } // R foo(); // ... // R r = foo(); // The first cursor on foo() will be a reference to the copy constructor and // this cursor will have a symbolLength of 1. Thus you won't be able to jump // to foo from the o. This is fixed by making sure the newer target, if // better, gets to decide on the symbolLength // The !isCursor is var decls and field decls where we set up a target even // if they're not considered references if (!RTags::isCursor(info.kind) && (!info.symbolLength || info.bestTarget(mData->symbols).kind == refKind)) { 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); info.start = start; info.end = end; info.definition = false; info.kind = kind; info.symbolLength = isOperator ? end - start : refInfo.symbolLength; info.symbolName = refInfo.symbolName; info.type = clang_getCursorType(cursor).kind; switch (kind) { case CXCursor_CallExpr: nestedClassConstructorCallUgleHack(parent, info, refKind, reffedLoc); // see rtags/tests/nestedClassConstructorCallUgleHack/ break; default: break; } } Set<Location> &val = mData->references[location]; val.insert(reffedLoc); }
SourceLocation getSourceLocation(CXSourceLocation location) const { unsigned line, column; clang_getSpellingLocation(location, 0, &line, &column, 0); return std::make_pair(line, column); }
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 source_location::spelling_location(CXFile *file, unsigned *line, unsigned *column, unsigned *offset) const { clang_getSpellingLocation(loc, file, line, column, offset); }
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 CursorHelper::getLineNumber(CXCursor cursor) { unsigned line; clang_getSpellingLocation(clang_getCursorLocation(cursor), 0, &line, 0, 0); return itoa(line); }
void ClangParser::writeSources(CodeOutputInterface &ol,FileDef *fd) { TooltipManager::instance()->clearTooltips(); // (re)set global parser state g_currentDefinition=0; g_currentMemberDef=0; g_currentLine=0; g_searchForBody=FALSE; g_insideBody=FALSE; g_bracketCount=0; unsigned int line=1,column=1; QCString lineNumber,lineAnchor; ol.startCodeLine(TRUE); writeLineNumber(ol,fd,line); for (unsigned int i=0;i<p->numTokens;i++) { CXSourceLocation start = clang_getTokenLocation(p->tu, p->tokens[i]); unsigned int l, c; clang_getSpellingLocation(start, 0, &l, &c, 0); if (l > line) column = 1; while (line<l) { line++; ol.endCodeLine(); ol.startCodeLine(TRUE); writeLineNumber(ol,fd,line); } while (column<c) { ol.codify(" "); column++; } CXString tokenString = clang_getTokenSpelling(p->tu, p->tokens[i]); char const *s = clang_getCString(tokenString); CXCursorKind cursorKind = clang_getCursorKind(p->cursors[i]); CXTokenKind tokenKind = clang_getTokenKind(p->tokens[i]); //printf("%d:%d %s cursorKind=%d tokenKind=%d\n",line,column,s,cursorKind,tokenKind); switch (tokenKind) { case CXToken_Keyword: if (strcmp(s,"operator")==0) { linkIdentifier(ol,fd,line,column,s,i); } else { codifyLines(ol,fd,s,line,column, cursorKind==CXCursor_PreprocessingDirective ? "preprocessor" : keywordToType(s)); } break; case CXToken_Literal: if (cursorKind==CXCursor_InclusionDirective) { linkInclude(ol,fd,line,column,s); } else if (s[0]=='"' || s[0]=='\'') { codifyLines(ol,fd,s,line,column,"stringliteral"); } else { codifyLines(ol,fd,s,line,column); } break; case CXToken_Comment: codifyLines(ol,fd,s,line,column,"comment"); break; default: // CXToken_Punctuation or CXToken_Identifier if (tokenKind==CXToken_Punctuation) { detectFunctionBody(s); //printf("punct %s: %d\n",s,cursorKind); } switch (cursorKind) { case CXCursor_PreprocessingDirective: codifyLines(ol,fd,s,line,column,"preprocessor"); break; case CXCursor_MacroDefinition: codifyLines(ol,fd,s,line,column,"preprocessor"); break; case CXCursor_InclusionDirective: linkInclude(ol,fd,line,column,s); break; case CXCursor_MacroExpansion: linkMacro(ol,fd,line,column,s); break; default: if (tokenKind==CXToken_Identifier || (tokenKind==CXToken_Punctuation && // for operators (cursorKind==CXCursor_DeclRefExpr || cursorKind==CXCursor_MemberRefExpr || cursorKind==CXCursor_CallExpr || cursorKind==CXCursor_ObjCMessageExpr) ) ) { linkIdentifier(ol,fd,line,column,s,i); if (Doxygen::searchIndex) { ol.addWord(s,FALSE); } } else { codifyLines(ol,fd,s,line,column); } break; } } clang_disposeString(tokenString); } ol.endCodeLine(); TooltipManager::instance()->writeTooltips(ol); }