diff options
-rw-r--r-- | src/plugins/clangcodemodel/clanghoverhandler.cpp | 77 | ||||
-rw-r--r-- | src/plugins/cpptools/cpptoolsreuse.cpp | 87 | ||||
-rw-r--r-- | src/plugins/cpptools/cpptoolsreuse.h | 1 |
3 files changed, 79 insertions, 86 deletions
diff --git a/src/plugins/clangcodemodel/clanghoverhandler.cpp b/src/plugins/clangcodemodel/clanghoverhandler.cpp index 58f414d9f1..c8e87c2577 100644 --- a/src/plugins/clangcodemodel/clanghoverhandler.cpp +++ b/src/plugins/clangcodemodel/clanghoverhandler.cpp @@ -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]() { diff --git a/src/plugins/cpptools/cpptoolsreuse.cpp b/src/plugins/cpptools/cpptoolsreuse.cpp index c56bfb9160..9bcf806b7d 100644 --- a/src/plugins/cpptools/cpptoolsreuse.cpp +++ b/src/plugins/cpptools/cpptoolsreuse.cpp @@ -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) diff --git a/src/plugins/cpptools/cpptoolsreuse.h b/src/plugins/cpptools/cpptoolsreuse.h index d1a1956be3..92e1365d15 100644 --- a/src/plugins/cpptools/cpptoolsreuse.h +++ b/src/plugins/cpptools/cpptoolsreuse.h @@ -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, |