Commit 7a09bb44 authored by Nikolai Kosjar's avatar Nikolai Kosjar

TextEditor: Reduce BaseHoverHandler::identifyMatch() calls

...because they are potentially expensive.

Change-Id: Iaa235ea1fa864a0a67f3ed10b7f89d23179c642b
Reviewed-by: David Schulz's avatarDavid Schulz <david.schulz@qt.io>
parent 0f7e6903
......@@ -29,6 +29,7 @@
#include "cppeditordocument.h"
#include <cpptools/cpptoolsreuse.h>
#include <texteditor/convenience.h>
#include <QTextBlock>
#include <QTextCursor>
......@@ -65,23 +66,6 @@ void CppUseSelectionsUpdater::abortSchedule()
m_timer.stop();
}
static QTextCursor cursorAtWordStart(const QTextCursor &textCursor)
{
const int originalPosition = textCursor.position();
QTextCursor cursor(textCursor);
cursor.movePosition(QTextCursor::StartOfWord);
const int wordStartPosition = cursor.position();
if (originalPosition == wordStartPosition) {
// Cursor is not on an identifier, check whether we are right after one.
const QChar c = textCursor.document()->characterAt(originalPosition - 1);
if (CppTools::isValidIdentifierChar(c))
cursor.movePosition(QTextCursor::PreviousWord);
}
return cursor;
}
void CppUseSelectionsUpdater::update(CallType callType)
{
auto *cppEditorWidget = qobject_cast<CppEditorWidget *>(m_editorWidget);
......@@ -92,7 +76,7 @@ void CppUseSelectionsUpdater::update(CallType callType)
CppTools::CursorInfoParams params;
params.semanticInfo = cppEditorWidget->semanticInfo();
params.textCursor = cursorAtWordStart(cppEditorWidget->textCursor());
params.textCursor = TextEditor::Convenience::wordStartCursor(cppEditorWidget->textCursor());
if (callType == Asynchronous) {
if (isSameIdentifierAsBefore(params.textCursor))
......@@ -150,8 +134,10 @@ void CppUseSelectionsUpdater::onFindUsesFinished()
return;
if (m_runnerRevision != m_editorWidget->document()->revision())
return;
if (m_runnerWordStartPosition != cursorAtWordStart(m_editorWidget->textCursor()).position())
if (m_runnerWordStartPosition
!= TextEditor::Convenience::wordStartCursor(m_editorWidget->textCursor()).position()) {
return;
}
processResults(m_runnerWatcher->result());
......
......@@ -33,9 +33,10 @@ namespace TextEditor {
BaseHoverHandler::~BaseHoverHandler()
{}
void BaseHoverHandler::showToolTip(TextEditorWidget *widget, const QPoint &point)
void BaseHoverHandler::showToolTip(TextEditorWidget *widget, const QPoint &point, bool decorate)
{
decorateToolTip();
if (decorate)
decorateToolTip();
operateTooltip(widget, point);
}
......
......@@ -44,7 +44,7 @@ public:
QString contextHelpId(TextEditorWidget *widget, int pos);
int checkToolTip(TextEditorWidget *widget, int pos);
void showToolTip(TextEditorWidget *widget, const QPoint &point);
void showToolTip(TextEditorWidget *widget, const QPoint &point, bool decorate = true);
protected:
enum {
......
......@@ -86,5 +86,31 @@ QTextCursor flippedCursor(const QTextCursor &cursor)
return flipped;
}
static bool isValidIdentifierChar(const QChar &c)
{
return c.isLetter()
|| c.isNumber()
|| c == QLatin1Char('_')
|| c.isHighSurrogate()
|| c.isLowSurrogate();
}
QTextCursor wordStartCursor(const QTextCursor &textCursor)
{
const int originalPosition = textCursor.position();
QTextCursor cursor(textCursor);
cursor.movePosition(QTextCursor::StartOfWord);
const int wordStartPosition = cursor.position();
if (originalPosition == wordStartPosition) {
// Cursor is not on an identifier, check whether we are right after one.
const QChar c = textCursor.document()->characterAt(originalPosition - 1);
if (isValidIdentifierChar(c))
cursor.movePosition(QTextCursor::PreviousWord);
}
return cursor;
}
} // Util
} // TextEditor
......@@ -47,5 +47,7 @@ TEXTEDITOR_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint c
TEXTEDITOR_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor);
TEXTEDITOR_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor);
} // Util
} // TextEditor
......@@ -468,6 +468,26 @@ public:
CodeAssistant m_codeAssistant;
bool m_assistRelevantContentAdded = false;
struct LastHoverHandlerInfo {
LastHoverHandlerInfo() = default;
LastHoverHandlerInfo(BaseHoverHandler *handler, int documentRevision, int cursorPosition)
: handler(handler)
, documentRevision(documentRevision)
, cursorPosition(cursorPosition)
{}
bool applies(int documentRevision, int cursorPosition) const
{
return handler
&& documentRevision == this->documentRevision
&& cursorPosition == this->cursorPosition;
}
BaseHoverHandler *handler = nullptr;
int documentRevision = -1;
int cursorPosition = -1;
} m_lastHoverHandlerInfo;
QList<BaseHoverHandler *> m_hoverHandlers; // Not owned
QPointer<QSequentialAnimationGroup> m_navigationAnimation;
......@@ -3161,6 +3181,15 @@ void TextEditorWidgetPrivate::processTooltipRequest(const QTextCursor &c)
return;
}
// Does the last handler still applies?
const int documentRevision = m_document->document()->revision();
const int cursorPosition = Convenience::wordStartCursor(c).position();
if (m_lastHoverHandlerInfo.applies(documentRevision, cursorPosition)) {
m_lastHoverHandlerInfo.handler->showToolTip(q, toolTipPoint, /*decorate=*/ false);
return;
}
// Determine best handler
int highestPriority = -1;
BaseHoverHandler *highest = 0;
foreach (BaseHoverHandler *handler, m_hoverHandlers) {
......@@ -3171,8 +3200,11 @@ void TextEditorWidgetPrivate::processTooltipRequest(const QTextCursor &c)
}
}
if (highest)
// Let the best handler show the tooltip
if (highest) {
m_lastHoverHandlerInfo = LastHoverHandlerInfo{highest, documentRevision, cursorPosition};
highest->showToolTip(q, toolTipPoint);
}
}
bool TextEditorWidgetPrivate::processAnnotaionTooltipRequest(const QTextBlock &block,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment