Move function to get fallback help IDs to CppTools

To be shared between Clang and Built-in model

Change-Id: Iebe132c93033c252c58da13b858a0dce61483eaf
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
Eike Ziller
2019-02-08 16:11:27 +01:00
parent 1c6db4ca8b
commit 9c492ce962
3 changed files with 79 additions and 86 deletions

View File

@@ -93,79 +93,6 @@ ClangHoverHandler::~ClangHoverHandler()
abort();
}
static int skipChars(QTextCursor *tc,
QTextCursor::MoveOperation op,
int offset,
std::function<bool(const QChar &)> skip)
{
const QTextDocument *doc = tc->document();
QChar ch = doc->characterAt(tc->position() + offset);
if (ch.isNull())
return 0;
int count = 0;
while (skip(ch)) {
if (tc->movePosition(op))
++count;
else
break;
ch = doc->characterAt(tc->position() + offset);
}
return count;
}
static int skipCharsForward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
{
return skipChars(tc, QTextCursor::NextCharacter, 0, skip);
}
static int skipCharsBackward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
{
return skipChars(tc, QTextCursor::PreviousCharacter, -1, skip);
}
static QStringList fallbackWords(QTextDocument *document, int pos)
{
const auto isSpace = [](const QChar &c) { return c.isSpace(); };
const auto isColon = [](const QChar &c) { return c == ':'; };
const auto isValidIdentifierChar = [document](const QTextCursor &tc) {
return CppTools::isValidIdentifierChar(document->characterAt(tc.position()));
};
// move to the end
QTextCursor endCursor(document);
endCursor.setPosition(pos);
do {
CppTools::moveCursorToEndOfIdentifier(&endCursor);
// possibly skip ::
QTextCursor temp(endCursor);
skipCharsForward(&temp, isSpace);
const int colons = skipCharsForward(&temp, isColon);
skipCharsForward(&temp, isSpace);
if (colons == 2 && isValidIdentifierChar(temp))
endCursor = temp;
} while (isValidIdentifierChar(endCursor));
QStringList results;
QTextCursor startCursor(endCursor);
do {
CppTools::moveCursorToStartOfIdentifier(&startCursor);
if (startCursor.position() == endCursor.position())
break;
QTextCursor temp(endCursor);
temp.setPosition(startCursor.position(), QTextCursor::KeepAnchor);
results.append(temp.selectedText().remove(QRegularExpression("\\s")));
// possibly skip ::
temp = startCursor;
skipCharsBackward(&temp, isSpace);
const int colons = skipCharsBackward(&temp, isColon);
skipCharsBackward(&temp, isSpace);
if (colons == 2
&& CppTools::isValidIdentifierChar(document->characterAt(temp.position() - 1))) {
startCursor = temp;
}
} while (!isValidIdentifierChar(startCursor));
return results;
}
void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
int pos,
BaseHoverHandler::ReportPriority report)
@@ -187,7 +114,9 @@ void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
qCDebug(hoverLog) << "Requesting tooltip info at" << pos;
m_reportPriority = report;
m_futureWatcher.reset(new QFutureWatcher<CppTools::ToolTipInfo>());
const QStringList fallback = fallbackWords(editorWidget->document(), pos);
QTextCursor tc(editorWidget->document());
tc.setPosition(pos);
const QStringList fallback = CppTools::identifierWordsUnderCursor(tc);
QObject::connect(m_futureWatcher.data(),
&QFutureWatcherBase::finished,
[this, fallback]() {

View File

@@ -41,6 +41,7 @@
#include <utils/qtcassert.h>
#include <QDebug>
#include <QRegularExpression>
#include <QSet>
#include <QStringRef>
#include <QTextCursor>
@@ -50,29 +51,91 @@ using namespace CPlusPlus;
namespace CppTools {
static void moveCursorToStartOrEndOfIdentifier(QTextCursor *tc,
QTextCursor::MoveOperation op,
int posDiff = 0)
static int skipChars(QTextCursor *tc,
QTextCursor::MoveOperation op,
int offset,
std::function<bool(const QChar &)> skip)
{
QTextDocument *doc = tc->document();
const QTextDocument *doc = tc->document();
if (!doc)
return;
QChar ch = doc->characterAt(tc->position() - posDiff);
while (isValidIdentifierChar(ch)) {
tc->movePosition(op);
ch = doc->characterAt(tc->position() - posDiff);
return 0;
QChar ch = doc->characterAt(tc->position() + offset);
if (ch.isNull())
return 0;
int count = 0;
while (skip(ch)) {
if (tc->movePosition(op))
++count;
else
break;
ch = doc->characterAt(tc->position() + offset);
}
return count;
}
static int skipCharsForward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
{
return skipChars(tc, QTextCursor::NextCharacter, 0, skip);
}
static int skipCharsBackward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
{
return skipChars(tc, QTextCursor::PreviousCharacter, -1, skip);
}
QStringList identifierWordsUnderCursor(const QTextCursor &tc)
{
const QTextDocument *document = tc.document();
if (!document)
return {};
const auto isSpace = [](const QChar &c) { return c.isSpace(); };
const auto isColon = [](const QChar &c) { return c == ':'; };
const auto isValidIdentifierCharAt = [document](const QTextCursor &tc) {
return isValidIdentifierChar(document->characterAt(tc.position()));
};
// move to the end
QTextCursor endCursor(tc);
do {
moveCursorToEndOfIdentifier(&endCursor);
// possibly skip ::
QTextCursor temp(endCursor);
skipCharsForward(&temp, isSpace);
const int colons = skipCharsForward(&temp, isColon);
skipCharsForward(&temp, isSpace);
if (colons == 2 && isValidIdentifierCharAt(temp))
endCursor = temp;
} while (isValidIdentifierCharAt(endCursor));
QStringList results;
QTextCursor startCursor(endCursor);
do {
moveCursorToStartOfIdentifier(&startCursor);
if (startCursor.position() == endCursor.position())
break;
QTextCursor temp(endCursor);
temp.setPosition(startCursor.position(), QTextCursor::KeepAnchor);
results.append(temp.selectedText().remove(QRegularExpression("\\s")));
// possibly skip ::
temp = startCursor;
skipCharsBackward(&temp, isSpace);
const int colons = skipCharsBackward(&temp, isColon);
skipCharsBackward(&temp, isSpace);
if (colons == 2
&& isValidIdentifierChar(document->characterAt(temp.position() - 1))) {
startCursor = temp;
}
} while (!isValidIdentifierCharAt(startCursor));
return results;
}
void moveCursorToEndOfIdentifier(QTextCursor *tc)
{
moveCursorToStartOrEndOfIdentifier(tc, QTextCursor::NextCharacter);
skipCharsForward(tc, isValidIdentifierChar);
}
void moveCursorToStartOfIdentifier(QTextCursor *tc)
{
moveCursorToStartOrEndOfIdentifier(tc, QTextCursor::PreviousCharacter, 1);
skipCharsBackward(tc, isValidIdentifierChar);
}
static bool isOwnershipRAIIName(const QString &name)

View File

@@ -58,6 +58,7 @@ bool CPPTOOLS_EXPORT isValidFirstIdentifierChar(const QChar &ch);
bool CPPTOOLS_EXPORT isValidIdentifierChar(const QChar &ch);
bool CPPTOOLS_EXPORT isValidIdentifier(const QString &s);
QStringList CPPTOOLS_EXPORT identifierWordsUnderCursor(const QTextCursor &tc);
QString CPPTOOLS_EXPORT identifierUnderCursor(QTextCursor *cursor);
bool CPPTOOLS_EXPORT isOwnershipRAIIType(CPlusPlus::Symbol *symbol,