forked from qt-creator/qt-creator
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:
@@ -93,79 +93,6 @@ ClangHoverHandler::~ClangHoverHandler()
|
|||||||
abort();
|
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,
|
void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
|
||||||
int pos,
|
int pos,
|
||||||
BaseHoverHandler::ReportPriority report)
|
BaseHoverHandler::ReportPriority report)
|
||||||
@@ -187,7 +114,9 @@ void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
|
|||||||
qCDebug(hoverLog) << "Requesting tooltip info at" << pos;
|
qCDebug(hoverLog) << "Requesting tooltip info at" << pos;
|
||||||
m_reportPriority = report;
|
m_reportPriority = report;
|
||||||
m_futureWatcher.reset(new QFutureWatcher<CppTools::ToolTipInfo>());
|
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(),
|
QObject::connect(m_futureWatcher.data(),
|
||||||
&QFutureWatcherBase::finished,
|
&QFutureWatcherBase::finished,
|
||||||
[this, fallback]() {
|
[this, fallback]() {
|
||||||
|
@@ -41,6 +41,7 @@
|
|||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QRegularExpression>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QStringRef>
|
#include <QStringRef>
|
||||||
#include <QTextCursor>
|
#include <QTextCursor>
|
||||||
@@ -50,29 +51,91 @@ using namespace CPlusPlus;
|
|||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
|
|
||||||
static void moveCursorToStartOrEndOfIdentifier(QTextCursor *tc,
|
static int skipChars(QTextCursor *tc,
|
||||||
QTextCursor::MoveOperation op,
|
QTextCursor::MoveOperation op,
|
||||||
int posDiff = 0)
|
int offset,
|
||||||
|
std::function<bool(const QChar &)> skip)
|
||||||
{
|
{
|
||||||
QTextDocument *doc = tc->document();
|
const QTextDocument *doc = tc->document();
|
||||||
if (!doc)
|
if (!doc)
|
||||||
return;
|
return 0;
|
||||||
|
QChar ch = doc->characterAt(tc->position() + offset);
|
||||||
QChar ch = doc->characterAt(tc->position() - posDiff);
|
if (ch.isNull())
|
||||||
while (isValidIdentifierChar(ch)) {
|
return 0;
|
||||||
tc->movePosition(op);
|
int count = 0;
|
||||||
ch = doc->characterAt(tc->position() - posDiff);
|
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)
|
void moveCursorToEndOfIdentifier(QTextCursor *tc)
|
||||||
{
|
{
|
||||||
moveCursorToStartOrEndOfIdentifier(tc, QTextCursor::NextCharacter);
|
skipCharsForward(tc, isValidIdentifierChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void moveCursorToStartOfIdentifier(QTextCursor *tc)
|
void moveCursorToStartOfIdentifier(QTextCursor *tc)
|
||||||
{
|
{
|
||||||
moveCursorToStartOrEndOfIdentifier(tc, QTextCursor::PreviousCharacter, 1);
|
skipCharsBackward(tc, isValidIdentifierChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isOwnershipRAIIName(const QString &name)
|
static bool isOwnershipRAIIName(const QString &name)
|
||||||
|
@@ -58,6 +58,7 @@ bool CPPTOOLS_EXPORT isValidFirstIdentifierChar(const QChar &ch);
|
|||||||
bool CPPTOOLS_EXPORT isValidIdentifierChar(const QChar &ch);
|
bool CPPTOOLS_EXPORT isValidIdentifierChar(const QChar &ch);
|
||||||
bool CPPTOOLS_EXPORT isValidIdentifier(const QString &s);
|
bool CPPTOOLS_EXPORT isValidIdentifier(const QString &s);
|
||||||
|
|
||||||
|
QStringList CPPTOOLS_EXPORT identifierWordsUnderCursor(const QTextCursor &tc);
|
||||||
QString CPPTOOLS_EXPORT identifierUnderCursor(QTextCursor *cursor);
|
QString CPPTOOLS_EXPORT identifierUnderCursor(QTextCursor *cursor);
|
||||||
|
|
||||||
bool CPPTOOLS_EXPORT isOwnershipRAIIType(CPlusPlus::Symbol *symbol,
|
bool CPPTOOLS_EXPORT isOwnershipRAIIType(CPlusPlus::Symbol *symbol,
|
||||||
|
Reference in New Issue
Block a user