forked from qt-creator/qt-creator
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:
10
src/libs/3rdparty/cplusplus/TranslationUnit.cpp
vendored
10
src/libs/3rdparty/cplusplus/TranslationUnit.cpp
vendored
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user