void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
                                           CppTools::ProjectPart *projectPart,
                                           RenameCallback &&renameSymbolsCallback)
{
    using CppTools::CompilerOptionsBuilder;

    setRefactoringEngineAvailable(false);

    m_client.setLocalRenamingCallback(std::move(renameSymbolsCallback));

    QString filePath = data.filePath().toString();
    QTextCursor textCursor = data.cursor();
    CompilerOptionsBuilder optionsBuilder{*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR};
    Utils::SmallStringVector commandLine{optionsBuilder.build(
                    fileKindInProjectPart(projectPart, filePath),
                    CppTools::getPchUsage())};

    commandLine.push_back(filePath);

    RequestSourceLocationsForRenamingMessage message(ClangBackEnd::FilePath(filePath),
                                                     uint(textCursor.blockNumber() + 1),
                                                     uint(textCursor.positionInBlock() + 1),
                                                     textCursor.document()->toPlainText(),
                                                     std::move(commandLine),
                                                     textCursor.document()->revision());


    m_server.requestSourceLocationsForRenamingMessage(std::move(message));
}
void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
                                           CppTools::ProjectPart *,
                                           RenameCallback &&renameSymbolsCallback)
{
    ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get(
        data.filePath().toString());
    const int startRevision = data.cursor().document()->revision();

    using ClangBackEnd::SourceLocationsContainer;
    auto defaultCallback = [renameSymbolsCallback, startRevision]() {
        return renameSymbolsCallback(QString(), SourceLocationsContainer{}, startRevision);
    };

    if (!processor)
        return defaultCallback();

    QFuture<CppTools::CursorInfo> cursorFuture = processor->requestLocalReferences(data.cursor());
    if (cursorFuture.isCanceled())
        return defaultCallback();

    if (m_watcher)
        m_watcher->cancel();

    m_watcher.reset(new FutureCursorWatcher());
    QObject::connect(m_watcher.get(), &FutureCursorWatcher::finished, [=]() {
        if (m_watcher->isCanceled())
            return defaultCallback();
        const CppTools::CursorInfo info = m_watcher->result();
        if (info.useRanges.empty())
            return defaultCallback();

        QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor());
        cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor,
                            info.useRanges.first().length);
        const QString symbolName = cursor.selectedText();
        ClangBackEnd::SourceLocationsContainer container;
        for (auto& use : info.useRanges) {
            container.insertSourceLocation(ClangBackEnd::FilePathId(),
                                           use.line,
                                           use.column,
                                           use.length);
        }
        renameSymbolsCallback(symbolName, container, data.cursor().document()->revision());
    });

    m_watcher->setFuture(cursorFuture);
}
CppTools::Usages RefactoringEngine::locationsAt(const CppTools::CursorInEditor &data) const
{
    CppTools::Usages usages;

    QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor());
    Utils::OptionalLineColumn lineColumn = Utils::Text::convertPosition(cursor.document(),
                                                                        cursor.position());

    if (lineColumn) {
        const QByteArray filePath = data.filePath().toString().toUtf8();
        const ClangBackEnd::FilePathId filePathId = m_filePathCache.filePathId(ClangBackEnd::FilePathView(filePath));

        usages = m_symbolQuery.sourceUsagesAt(filePathId, lineColumn->line, lineColumn->column + 1);
    }

    return usages;
}
void RefactoringEngine::globalFollowSymbol(const CppTools::CursorInEditor &data,
                                           Utils::ProcessLinkCallback &&processLinkCallback,
                                           const CPlusPlus::Snapshot &,
                                           const CPlusPlus::Document::Ptr &,
                                           CppTools::SymbolFinder *,
                                           bool) const
{
    // TODO: replace that with specific followSymbol query
    const CppTools::Usages usages = locationsAt(data);
    CppTools::Usage usage = Utils::findOrDefault(usages, [&data](const CppTools::Usage &usage) {
        // We've already searched in the current file, skip it.
        if (usage.path == data.filePath().toString())
            return false;
        return true;
    });

    processLinkCallback(Link(usage.path, usage.line, usage.column));
}