CppEditor: Consider selection when requesting quickfixes

If the user has a token selected, prefer that to the actual cursor
position.

Fixes: QTCREATORBUG-27886
Change-Id: Ib32e24676510bff42292fe23e4962720fcbac4ed
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2022-08-22 16:46:57 +02:00
parent 13a9f6663b
commit 5817bdf87d
4 changed files with 63 additions and 2 deletions

View File

@@ -26,6 +26,9 @@
#include "AST.h"
#include "Literals.h"
#include "DiagnosticClient.h"
#include <utils/textutils.h>
#include <stack>
#include <vector>
#include <cstdarg>
@@ -382,6 +385,13 @@ void TranslationUnit::getTokenPosition(int index,
const StringLiteral **fileName) const
{ return getPosition(tokenAt(index).utf16charsBegin(), line, column, fileName); }
int TranslationUnit::getTokenPositionInDocument(int index, const QTextDocument *doc) const
{
int line, column;
getTokenPosition(index, &line, &column);
return Utils::Text::positionInText(doc, line, column);
}
void TranslationUnit::getTokenStartPosition(int index, int *line,
int *column,
const StringLiteral **fileName) const

View File

@@ -28,6 +28,10 @@
#include <unordered_map>
#include <vector>
QT_BEGIN_NAMESPACE
class QTextDocument;
QT_END_NAMESPACE
namespace CPlusPlus {
class CPLUSPLUS_EXPORT TranslationUnit
@@ -124,6 +128,8 @@ public:
int *column = nullptr,
const StringLiteral **fileName = nullptr) const;
int getTokenPositionInDocument(int index, const QTextDocument *doc) const;
void pushLineOffset(int offset);
void pushPreprocessorLine(int utf16charOffset,
int line,

View File

@@ -86,7 +86,7 @@ CppQuickFixInterface::CppQuickFixInterface(CppEditorWidget *editor, AssistReason
QTC_CHECK(m_semanticInfo.doc->translationUnit());
QTC_CHECK(m_semanticInfo.doc->translationUnit()->ast());
ASTPath astPath(m_semanticInfo.doc);
m_path = astPath(editor->textCursor());
m_path = astPath(adjustedCursor());
}
const QList<AST *> &CppQuickFixInterface::path() const
@@ -129,6 +129,50 @@ bool CppQuickFixInterface::isCursorOn(const AST *ast) const
return currentFile()->isCursorOn(ast);
}
// Some users like to select identifiers and expect the quickfix to apply to the selection.
// However, as the cursor position is at the end of the selection, it can happen that
// the quickfix is applied to the following token instead; see e.g. QTCREATORBUG-27886.
// We try to detect this condition: If there is a selection *and* this selection
// corresponds to a C++ token, we move the cursor to that token's position.
QTextCursor CppQuickFixInterface::adjustedCursor()
{
QTextCursor cursor = this->cursor();
if (!cursor.hasSelection())
return cursor;
const TranslationUnit * const tu = m_semanticInfo.doc->translationUnit();
const int selStart = cursor.selectionStart();
const int selEnd = cursor.selectionEnd();
const QTextDocument * const doc = m_editor->textDocument()->document();
// Binary search for matching token.
for (int l = 0, u = tu->tokenCount() - 1; l <= u; ) {
const int i = (l + u) / 2;
const int tokenPos = tu->getTokenPositionInDocument(i, doc);
if (selStart < tokenPos) {
u = i - 1;
continue;
}
if (selStart > tokenPos) {
l = i + 1;
continue;
}
// Selection does not end at token end.
if (tokenPos + tu->tokenAt(i).utf16chars() != selEnd)
break;
cursor.setPosition(selStart);
// Try not to have the cursor "at the edge", in order to prevent potential ambiguities.
if (selEnd - selStart > 1)
cursor.setPosition(cursor.position() + 1);
return cursor;
}
return cursor;
}
QuickFixOperations quickFixOperations(const TextEditor::AssistInterface *interface)
{
const auto cppInterface = dynamic_cast<const CppQuickFixInterface *>(interface);

View File

@@ -33,7 +33,6 @@
#include <cplusplus/LookupContext.h>
namespace CppEditor {
class CppEditorWidget;
class CppRefactoringFile;
@@ -59,6 +58,8 @@ public:
bool isBaseObject() const override { return false; }
private:
QTextCursor adjustedCursor();
CppEditorWidget *m_editor;
SemanticInfo m_semanticInfo;
CPlusPlus::Snapshot m_snapshot;