TextEditor: add text cursor to assist interface

This will allow us to request assistance for a specific selection
instead of just the position.

Change-Id: Ib8e5b32d4a8f2936e5a6f1b7ac968d7f1d8d9de6
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
David Schulz
2022-05-13 10:05:45 +02:00
parent 1402b16451
commit 59a77a4965
18 changed files with 44 additions and 60 deletions

View File

@@ -616,18 +616,13 @@ void addFixItsActionsToMenu(QMenu *menu, const TextEditor::QuickFixOperations &f
} }
} }
static int lineToPosition(const QTextDocument *textDocument, int lineNumber)
{
QTC_ASSERT(textDocument, return 0);
const QTextBlock textBlock = textDocument->findBlockByLineNumber(lineNumber);
return textBlock.isValid() ? textBlock.position() - 1 : 0;
}
static TextEditor::AssistInterface createAssistInterface(TextEditor::TextEditorWidget *widget, static TextEditor::AssistInterface createAssistInterface(TextEditor::TextEditorWidget *widget,
int lineNumber) int lineNumber)
{ {
return TextEditor::AssistInterface(widget->document(), QTextCursor cursor(widget->document()->findBlockByLineNumber(lineNumber));
lineToPosition(widget->document(), lineNumber), if (!cursor.atStart())
cursor.movePosition(QTextCursor::PreviousCharacter);
return TextEditor::AssistInterface(cursor,
widget->textDocument()->filePath(), widget->textDocument()->filePath(),
TextEditor::IdleEditor); TextEditor::IdleEditor);
} }

View File

@@ -105,9 +105,12 @@ public:
QStringList completions; QStringList completions;
LanguageFeatures languageFeatures = LanguageFeatures::defaultFeatures(); LanguageFeatures languageFeatures = LanguageFeatures::defaultFeatures();
languageFeatures.objCEnabled = false; languageFeatures.objCEnabled = false;
QTextCursor textCursor = m_editorWidget->textCursor();
textCursor.setPosition(m_position);
m_editorWidget->setTextCursor(textCursor);
CppCompletionAssistInterface *ai CppCompletionAssistInterface *ai
= new CppCompletionAssistInterface(m_editorWidget->textDocument()->filePath(), = new CppCompletionAssistInterface(m_editorWidget->textDocument()->filePath(),
m_textDocument, m_position, m_editorWidget,
ExplicitlyInvoked, m_snapshot, ExplicitlyInvoked, m_snapshot,
ProjectExplorer::HeaderPaths(), ProjectExplorer::HeaderPaths(),
languageFeatures); languageFeatures);

View File

@@ -426,7 +426,6 @@ AssistInterface *InternalCompletionAssistProvider::createAssistInterface(
const Utils::FilePath &filePath, const Utils::FilePath &filePath,
const TextEditorWidget *textEditorWidget, const TextEditorWidget *textEditorWidget,
const LanguageFeatures &languageFeatures, const LanguageFeatures &languageFeatures,
int position,
AssistReason reason) const AssistReason reason) const
{ {
QTC_ASSERT(textEditorWidget, return nullptr); QTC_ASSERT(textEditorWidget, return nullptr);
@@ -435,7 +434,6 @@ AssistInterface *InternalCompletionAssistProvider::createAssistInterface(
textEditorWidget, textEditorWidget,
BuiltinEditorDocumentParser::get(filePath.toString()), BuiltinEditorDocumentParser::get(filePath.toString()),
languageFeatures, languageFeatures,
position,
reason, reason,
CppModelManager::instance()->workingCopy()); CppModelManager::instance()->workingCopy());
} }

View File

@@ -87,7 +87,6 @@ public:
const Utils::FilePath &filePath, const Utils::FilePath &filePath,
const TextEditor::TextEditorWidget *textEditorWidget, const TextEditor::TextEditorWidget *textEditorWidget,
const CPlusPlus::LanguageFeatures &languageFeatures, const CPlusPlus::LanguageFeatures &languageFeatures,
int position,
TextEditor::AssistReason reason) const override; TextEditor::AssistReason reason) const override;
}; };
@@ -168,10 +167,9 @@ public:
const TextEditor::TextEditorWidget *textEditorWidget, const TextEditor::TextEditorWidget *textEditorWidget,
BuiltinEditorDocumentParser::Ptr parser, BuiltinEditorDocumentParser::Ptr parser,
const CPlusPlus::LanguageFeatures &languageFeatures, const CPlusPlus::LanguageFeatures &languageFeatures,
int position,
TextEditor::AssistReason reason, TextEditor::AssistReason reason,
const WorkingCopy &workingCopy) const WorkingCopy &workingCopy)
: TextEditor::AssistInterface(textEditorWidget->document(), position, filePath, reason) : TextEditor::AssistInterface(textEditorWidget->textCursor(), filePath, reason)
, m_parser(parser) , m_parser(parser)
, m_gotCppSpecifics(false) , m_gotCppSpecifics(false)
, m_workingCopy(workingCopy) , m_workingCopy(workingCopy)
@@ -179,13 +177,12 @@ public:
{} {}
CppCompletionAssistInterface(const Utils::FilePath &filePath, CppCompletionAssistInterface(const Utils::FilePath &filePath,
QTextDocument *textDocument, const TextEditor::TextEditorWidget *textEditorWidget,
int position,
TextEditor::AssistReason reason, TextEditor::AssistReason reason,
const CPlusPlus::Snapshot &snapshot, const CPlusPlus::Snapshot &snapshot,
const ProjectExplorer::HeaderPaths &headerPaths, const ProjectExplorer::HeaderPaths &headerPaths,
const CPlusPlus::LanguageFeatures &features) const CPlusPlus::LanguageFeatures &features)
: TextEditor::AssistInterface(textDocument, position, filePath, reason) : TextEditor::AssistInterface(textEditorWidget->textCursor(), filePath, reason)
, m_gotCppSpecifics(true) , m_gotCppSpecifics(true)
, m_snapshot(snapshot) , m_snapshot(snapshot)
, m_headerPaths(headerPaths) , m_headerPaths(headerPaths)

View File

@@ -59,7 +59,6 @@ public:
const Utils::FilePath &filePath, const Utils::FilePath &filePath,
const TextEditor::TextEditorWidget *textEditorWidget, const TextEditor::TextEditorWidget *textEditorWidget,
const CPlusPlus::LanguageFeatures &languageFeatures, const CPlusPlus::LanguageFeatures &languageFeatures,
int position,
TextEditor::AssistReason reason) const = 0; TextEditor::AssistReason reason) const = 0;
static int activationSequenceChar(const QChar &ch, const QChar &ch2, static int activationSequenceChar(const QChar &ch, const QChar &ch2,

View File

@@ -1312,7 +1312,6 @@ AssistInterface *CppEditorWidget::createAssistInterface(AssistKind kind, AssistR
return cap->createAssistInterface(textDocument()->filePath(), return cap->createAssistInterface(textDocument()->filePath(),
this, this,
features, features,
position(),
reason); reason);
} else { } else {
return TextEditorWidget::createAssistInterface(kind, reason); return TextEditorWidget::createAssistInterface(kind, reason);

View File

@@ -74,10 +74,8 @@ IAssistProcessor *CppQuickFixAssistProvider::createProcessor(const AssistInterfa
// -------------------------- // --------------------------
// CppQuickFixAssistInterface // CppQuickFixAssistInterface
// -------------------------- // --------------------------
CppQuickFixInterface::CppQuickFixInterface(CppEditorWidget *editor, CppQuickFixInterface::CppQuickFixInterface(CppEditorWidget *editor, AssistReason reason)
AssistReason reason) : AssistInterface(editor->textCursor(), editor->textDocument()->filePath(), reason)
: AssistInterface(editor->document(), editor->position(),
editor->textDocument()->filePath(), reason)
, m_editor(editor) , m_editor(editor)
, m_semanticInfo(editor->semanticInfo()) , m_semanticInfo(editor->semanticInfo())
, m_snapshot(CppModelManager::instance()->snapshot()) , m_snapshot(CppModelManager::instance()->snapshot())

View File

@@ -545,13 +545,12 @@ bool GlslCompletionAssistProcessor::acceptsIdleEditor() const
// ----------------------------- // -----------------------------
// GlslCompletionAssistInterface // GlslCompletionAssistInterface
// ----------------------------- // -----------------------------
GlslCompletionAssistInterface::GlslCompletionAssistInterface(QTextDocument *textDocument, GlslCompletionAssistInterface::GlslCompletionAssistInterface(const QTextCursor &cursor,
int position,
const Utils::FilePath &fileName, const Utils::FilePath &fileName,
AssistReason reason, AssistReason reason,
const QString &mimeType, const QString &mimeType,
const Document::Ptr &glslDoc) const Document::Ptr &glslDoc)
: AssistInterface(textDocument, position, fileName, reason) : AssistInterface(cursor, fileName, reason)
, m_mimeType(mimeType) , m_mimeType(mimeType)
, m_glslDoc(glslDoc) , m_glslDoc(glslDoc)
{ {

View File

@@ -107,8 +107,7 @@ private:
class GlslCompletionAssistInterface : public TextEditor::AssistInterface class GlslCompletionAssistInterface : public TextEditor::AssistInterface
{ {
public: public:
GlslCompletionAssistInterface(QTextDocument *textDocument, GlslCompletionAssistInterface(const QTextCursor &cursor, const Utils::FilePath &fileName,
int position, const Utils::FilePath &fileName,
TextEditor::AssistReason reason, TextEditor::AssistReason reason,
const QString &mimeType, const QString &mimeType,
const Document::Ptr &glslDoc); const Document::Ptr &glslDoc);

View File

@@ -369,8 +369,7 @@ AssistInterface *GlslEditorWidget::createAssistInterface(
AssistKind kind, AssistReason reason) const AssistKind kind, AssistReason reason) const
{ {
if (kind == Completion) if (kind == Completion)
return new GlslCompletionAssistInterface(document(), return new GlslCompletionAssistInterface(textCursor(),
position(),
textDocument()->filePath(), textDocument()->filePath(),
reason, reason,
textDocument()->mimeType(), textDocument()->mimeType(),

View File

@@ -103,7 +103,7 @@ TextEditor::AssistInterface *BindingEditorWidget::createAssistInterface(
{ {
Q_UNUSED(assistKind) Q_UNUSED(assistKind)
return new QmlJSEditor::QmlJSCompletionAssistInterface( return new QmlJSEditor::QmlJSCompletionAssistInterface(
document(), position(), Utils::FilePath(), textCursor(), Utils::FilePath(),
assistReason, qmljsdocument->semanticInfo()); assistReason, qmljsdocument->semanticInfo());
} }

View File

@@ -334,10 +334,11 @@ QStringList qmlJSAutoComplete(QTextDocument *textDocument,
{ {
QStringList list; QStringList list;
QmlJSCompletionAssistProcessor processor; QmlJSCompletionAssistProcessor processor;
QTextCursor cursor(textDocument);
cursor.setPosition(position);
QScopedPointer<IAssistProposal> proposal(processor.perform( /* The processor takes ownership. */ QScopedPointer<IAssistProposal> proposal(processor.perform( /* The processor takes ownership. */
new QmlJSCompletionAssistInterface( new QmlJSCompletionAssistInterface(
textDocument, cursor,
position,
fileName, fileName,
reason, reason,
info))); info)));
@@ -978,12 +979,11 @@ bool QmlJSCompletionAssistProcessor::completeUrl(const QString &relativeBasePath
// ------------------------------ // ------------------------------
// QmlJSCompletionAssistInterface // QmlJSCompletionAssistInterface
// ------------------------------ // ------------------------------
QmlJSCompletionAssistInterface::QmlJSCompletionAssistInterface(QTextDocument *textDocument, QmlJSCompletionAssistInterface::QmlJSCompletionAssistInterface(const QTextCursor &cursor,
int position,
const Utils::FilePath &fileName, const Utils::FilePath &fileName,
AssistReason reason, AssistReason reason,
const SemanticInfo &info) const SemanticInfo &info)
: AssistInterface(textDocument, position, fileName, reason) : AssistInterface(cursor, fileName, reason)
, m_semanticInfo(info) , m_semanticInfo(info)
{} {}

View File

@@ -105,8 +105,7 @@ private:
class QMLJSEDITOR_EXPORT QmlJSCompletionAssistInterface : public TextEditor::AssistInterface class QMLJSEDITOR_EXPORT QmlJSCompletionAssistInterface : public TextEditor::AssistInterface
{ {
public: public:
QmlJSCompletionAssistInterface(QTextDocument *textDocument, QmlJSCompletionAssistInterface(const QTextCursor &cursor,
int position,
const Utils::FilePath &fileName, const Utils::FilePath &fileName,
TextEditor::AssistReason reason, TextEditor::AssistReason reason,
const QmlJSTools::SemanticInfo &info); const QmlJSTools::SemanticInfo &info);

View File

@@ -1021,11 +1021,8 @@ AssistInterface *QmlJSEditorWidget::createAssistInterface(
AssistReason reason) const AssistReason reason) const
{ {
if (assistKind == Completion) { if (assistKind == Completion) {
return new QmlJSCompletionAssistInterface(document(), return new QmlJSCompletionAssistInterface(textCursor(), textDocument()->filePath(),
position(), reason, m_qmlJsEditorDocument->semanticInfo());
textDocument()->filePath(),
reason,
m_qmlJsEditorDocument->semanticInfo());
} else if (assistKind == QuickFix) { } else if (assistKind == QuickFix) {
return new Internal::QmlJSQuickFixAssistInterface(const_cast<QmlJSEditorWidget *>(this), reason); return new Internal::QmlJSQuickFixAssistInterface(const_cast<QmlJSEditorWidget *>(this), reason);
} }

View File

@@ -48,8 +48,7 @@ using namespace Internal;
// ----------------------- // -----------------------
QmlJSQuickFixAssistInterface::QmlJSQuickFixAssistInterface(QmlJSEditorWidget *editor, QmlJSQuickFixAssistInterface::QmlJSQuickFixAssistInterface(QmlJSEditorWidget *editor,
AssistReason reason) AssistReason reason)
: AssistInterface(editor->document(), editor->position(), : AssistInterface(editor->textCursor(), editor->textDocument()->filePath(), reason)
editor->textDocument()->filePath(), reason)
, m_semanticInfo(editor->qmlJsEditorDocument()->semanticInfo()) , m_semanticInfo(editor->qmlJsEditorDocument()->semanticInfo())
, m_currentFile(QmlJSRefactoringChanges::file(editor, m_semanticInfo.document)) , m_currentFile(QmlJSRefactoringChanges::file(editor, m_semanticInfo.document))
{} {}

View File

@@ -101,13 +101,14 @@ using namespace TextEditor;
namespace TextEditor { namespace TextEditor {
AssistInterface::AssistInterface(QTextDocument *textDocument, AssistInterface::AssistInterface(const QTextCursor &cursor,
int position,
const Utils::FilePath &filePath, const Utils::FilePath &filePath,
AssistReason reason) AssistReason reason)
: m_textDocument(textDocument) : m_textDocument(cursor.document())
, m_cursor(cursor)
, m_isAsync(false) , m_isAsync(false)
, m_position(position) , m_position(cursor.position())
, m_anchor(cursor.anchor())
, m_filePath(filePath) , m_filePath(filePath)
, m_reason(reason) , m_reason(reason)
{} {}
@@ -141,6 +142,9 @@ void AssistInterface::prepareForAsyncUse()
void AssistInterface::recreateTextDocument() void AssistInterface::recreateTextDocument()
{ {
m_textDocument = new QTextDocument(m_text); m_textDocument = new QTextDocument(m_text);
m_cursor = QTextCursor(m_textDocument);
m_cursor.setPosition(m_anchor);
m_cursor.setPosition(m_position, QTextCursor::KeepAnchor);
m_text.clear(); m_text.clear();
QTC_CHECK(m_textDocument->blockCount() == m_userStates.count()); QTC_CHECK(m_textDocument->blockCount() == m_userStates.count());

View File

@@ -30,21 +30,17 @@
#include <texteditor/texteditor_global.h> #include <texteditor/texteditor_global.h>
#include <QString> #include <QString>
#include <QTextCursor>
#include <QVector> #include <QVector>
#include <utils/fileutils.h> #include <utils/fileutils.h>
QT_BEGIN_NAMESPACE
class QTextDocument;
QT_END_NAMESPACE
namespace TextEditor { namespace TextEditor {
class TEXTEDITOR_EXPORT AssistInterface class TEXTEDITOR_EXPORT AssistInterface
{ {
public: public:
AssistInterface(QTextDocument *textDocument, AssistInterface(const QTextCursor &cursor,
int position,
const Utils::FilePath &filePath, const Utils::FilePath &filePath,
AssistReason reason); AssistReason reason);
virtual ~AssistInterface(); virtual ~AssistInterface();
@@ -52,6 +48,7 @@ public:
virtual int position() const { return m_position; } virtual int position() const { return m_position; }
virtual QChar characterAt(int position) const; virtual QChar characterAt(int position) const;
virtual QString textAt(int position, int length) const; virtual QString textAt(int position, int length) const;
QTextCursor cursor() const { return m_cursor; }
virtual Utils::FilePath filePath() const { return m_filePath; } virtual Utils::FilePath filePath() const { return m_filePath; }
virtual QTextDocument *textDocument() const { return m_textDocument; } virtual QTextDocument *textDocument() const { return m_textDocument; }
virtual void prepareForAsyncUse(); virtual void prepareForAsyncUse();
@@ -60,8 +57,10 @@ public:
private: private:
QTextDocument *m_textDocument; QTextDocument *m_textDocument;
QTextCursor m_cursor;
bool m_isAsync; bool m_isAsync;
int m_position; int m_position;
int m_anchor;
Utils::FilePath m_filePath; Utils::FilePath m_filePath;
AssistReason m_reason; AssistReason m_reason;
QString m_text; QString m_text;

View File

@@ -8172,7 +8172,7 @@ AssistInterface *TextEditorWidget::createAssistInterface(AssistKind kind,
AssistReason reason) const AssistReason reason) const
{ {
Q_UNUSED(kind) Q_UNUSED(kind)
return new AssistInterface(document(), position(), d->m_document->filePath(), reason); return new AssistInterface(textCursor(), d->m_document->filePath(), reason);
} }
QString TextEditorWidget::foldReplacementText(const QTextBlock &) const QString TextEditorWidget::foldReplacementText(const QTextBlock &) const