SourceRangeContainer FollowSymbol::followSymbol(CXTranslationUnit tu, const Cursor &fullCursor, uint line, uint column) { std::unique_ptr<Tokens> tokens(new Tokens(fullCursor)); if (!tokens->tokenCount) tokens.reset(new Tokens(tu)); if (!tokens->tokenCount) return SourceRangeContainer(); QVector<CXCursor> cursors(static_cast<int>(tokens->tokenCount)); clang_annotateTokens(tu, tokens->data, tokens->tokenCount, cursors.data()); int tokenIndex = getTokenIndex(tu, *tokens, line, column); QTC_ASSERT(tokenIndex >= 0, return SourceRangeContainer()); const Utf8String tokenSpelling = ClangString( clang_getTokenSpelling(tu, tokens->data[tokenIndex])); if (tokenSpelling.isEmpty()) return SourceRangeContainer(); Cursor cursor{cursors[tokenIndex]}; if (cursor.kind() == CXCursor_InclusionDirective) { CXFile file = clang_getIncludedFile(cursors[tokenIndex]); const ClangString filename(clang_getFileName(file)); const SourceLocation loc(tu, filename, 1, 1); return SourceRange(loc, loc); } // For definitions we can always find a declaration in current TU if (cursor.isDefinition()) return extractMatchingTokenRange(cursor.canonical(), tokenSpelling); if (!cursor.isDeclaration()) { // This is the symbol usage // We want to return definition cursor = cursor.referenced(); if (cursor.isNull() || !cursor.isDefinition()) { // We can't find definition in this TU return SourceRangeContainer(); } return extractMatchingTokenRange(cursor, tokenSpelling); } cursor = cursor.definition(); // If we are able to find a definition in current TU if (!cursor.isNull()) return extractMatchingTokenRange(cursor, tokenSpelling); return SourceRangeContainer(); }
SourceRangeContainer SourceRange::toSourceRangeContainer() const { return SourceRangeContainer(start().toSourceLocationContainer(), end().toSourceLocationContainer()); }