diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/clangcodemodel/clanghoverhandler.cpp | 115 | ||||
-rw-r--r-- | src/plugins/clangcodemodel/clanghoverhandler.h | 1 | ||||
-rw-r--r-- | src/plugins/cpptools/cpphoverhandler.cpp | 39 | ||||
-rw-r--r-- | src/plugins/cpptools/cpphoverhandler.h | 1 | ||||
-rw-r--r-- | src/plugins/texteditor/basehoverhandler.cpp | 8 |
5 files changed, 106 insertions, 58 deletions
diff --git a/src/plugins/clangcodemodel/clanghoverhandler.cpp b/src/plugins/clangcodemodel/clanghoverhandler.cpp index be59805170..1dc294cab5 100644 --- a/src/plugins/clangcodemodel/clanghoverhandler.cpp +++ b/src/plugins/clangcodemodel/clanghoverhandler.cpp @@ -28,6 +28,7 @@ #include <coreplugin/helpmanager.h> #include <cpptools/baseeditordocumentprocessor.h> #include <cpptools/cppmodelmanager.h> +#include <cpptools/cpptoolsreuse.h> #include <cpptools/editordocumenthandle.h> #include <texteditor/texteditor.h> @@ -37,6 +38,7 @@ #include <QFutureWatcher> #include <QLoggingCategory> +#include <QRegularExpression> #include <QTextCodec> #include <QVBoxLayout> @@ -105,6 +107,79 @@ 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) @@ -118,8 +193,6 @@ void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget, qCDebug(hoverLog) << "Checking for diagnostic at" << pos; setPriority(Priority_Diagnostic); m_cursorPosition = pos; - report(priority()); - return; } // Check for tooltips (async) @@ -128,17 +201,25 @@ void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget, qCDebug(hoverLog) << "Requesting tooltip info at" << pos; m_reportPriority = report; m_futureWatcher.reset(new QFutureWatcher<CppTools::ToolTipInfo>()); - QObject::connect(m_futureWatcher.data(), &QFutureWatcherBase::finished, [this]() { - if (m_futureWatcher->isCanceled()) - m_reportPriority(Priority_None); - else - processToolTipInfo(m_futureWatcher->result()); - }); + const QStringList fallback = fallbackWords(editorWidget->document(), pos); + QObject::connect(m_futureWatcher.data(), + &QFutureWatcherBase::finished, + [this, fallback]() { + if (m_futureWatcher->isCanceled()) { + m_reportPriority(Priority_None); + } else { + CppTools::ToolTipInfo info = m_futureWatcher->result(); + qCDebug(hoverLog) + << "Appending word-based fallback lookup" << fallback; + info.qDocIdCandidates += fallback; + processToolTipInfo(info); + } + }); m_futureWatcher->setFuture(future); return; } - report(Priority_None); // Ops, something went wrong. + report(priority()); // Ops, something went wrong. } void ClangHoverHandler::abort() @@ -198,22 +279,6 @@ void ClangHoverHandler::processToolTipInfo(const CppTools::ToolTipInfo &info) m_reportPriority(priority()); } -void ClangHoverHandler::decorateToolTip() -{ - if (priority() == Priority_Diagnostic) - return; - - if (Qt::mightBeRichText(toolTip())) - setToolTip(toolTip().toHtmlEscaped()); - - const HelpItem &help = lastHelpItemIdentified(); - if (help.isValid()) { - const QString text = CppTools::CppHoverHandler::tooltipTextForHelpItem(help); - if (!text.isEmpty()) - setToolTip(text); - } -} - void ClangHoverHandler::operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) { diff --git a/src/plugins/clangcodemodel/clanghoverhandler.h b/src/plugins/clangcodemodel/clanghoverhandler.h index 7f7bdbb18d..0bf1d88ee3 100644 --- a/src/plugins/clangcodemodel/clanghoverhandler.h +++ b/src/plugins/clangcodemodel/clanghoverhandler.h @@ -42,7 +42,6 @@ public: void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int pos, ReportPriority report) override; - void decorateToolTip() override; void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override; private: diff --git a/src/plugins/cpptools/cpphoverhandler.cpp b/src/plugins/cpptools/cpphoverhandler.cpp index 3969065ff7..752f50725b 100644 --- a/src/plugins/cpptools/cpphoverhandler.cpp +++ b/src/plugins/cpptools/cpphoverhandler.cpp @@ -30,6 +30,7 @@ #include <coreplugin/helpmanager.h> #include <texteditor/texteditor.h> +#include <utils/optional.h> #include <utils/textutils.h> #include <utils/executeondestruction.h> @@ -78,47 +79,31 @@ void CppHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, Rep CppElementEvaluator evaluator(editorWidget); evaluator.setTextCursor(tc); evaluator.execute(); + QString tip; if (evaluator.hasDiagnosis()) { - setToolTip(evaluator.diagnosis()); + tip += evaluator.diagnosis(); setPriority(Priority_Diagnostic); - } else if (evaluator.identifiedCppElement()) { + } + if (evaluator.identifiedCppElement()) { const QSharedPointer<CppElement> &cppElement = evaluator.cppElement(); - if (priority() != Priority_Diagnostic) { - setToolTip(cppElement->tooltip); - setPriority(cppElement->tooltip.isEmpty() ? Priority_None : Priority_Tooltip); - } QStringList candidates = cppElement->helpIdCandidates; candidates.removeDuplicates(); + Utils::optional<HelpItem> helpItem; foreach (const QString &helpId, candidates) { if (helpId.isEmpty()) continue; - const QMap<QString, QUrl> helpLinks = HelpManager::linksForIdentifier(helpId); if (!helpLinks.isEmpty()) { - setLastHelpItemIdentified(HelpItem(helpId, - cppElement->helpMark, - cppElement->helpCategory, - helpLinks)); + helpItem.emplace(helpId, cppElement->helpMark, cppElement->helpCategory, helpLinks); break; } } + if (helpItem) + setLastHelpItemIdentified(helpItem.value()); // tool tip appended by decorateToolTip + else + tip += cppElement->tooltip; } -} - -void CppHoverHandler::decorateToolTip() -{ - if (Qt::mightBeRichText(toolTip())) - setToolTip(toolTip().toHtmlEscaped()); - - if (priority() == Priority_Diagnostic) - return; - - const HelpItem &help = lastHelpItemIdentified(); - if (help.isValid()) { - const QString text = tooltipTextForHelpItem(help); - if (!text.isEmpty()) - setToolTip(text); - } + setToolTip(tip); } } // namespace CppTools diff --git a/src/plugins/cpptools/cpphoverhandler.h b/src/plugins/cpptools/cpphoverhandler.h index 75d6475537..6905605fab 100644 --- a/src/plugins/cpptools/cpphoverhandler.h +++ b/src/plugins/cpptools/cpphoverhandler.h @@ -40,7 +40,6 @@ private: void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int pos, ReportPriority report) override; - void decorateToolTip() override; }; } // namespace CppTools diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp index 157397ef2f..7eb5bc70b6 100644 --- a/src/plugins/texteditor/basehoverhandler.cpp +++ b/src/plugins/texteditor/basehoverhandler.cpp @@ -148,11 +148,11 @@ void BaseHoverHandler::decorateToolTip() if (Qt::mightBeRichText(toolTip())) setToolTip(toolTip().toHtmlEscaped()); - if (priority() != Priority_Diagnostic && lastHelpItemIdentified().isValid()) { - const QString &contents = lastHelpItemIdentified().extractContent(false); - if (!contents.isEmpty()) { + if (lastHelpItemIdentified().isValid()) { + const QString &helpContents = lastHelpItemIdentified().extractContent(false); + if (!helpContents.isEmpty()) { m_toolTip = toolTip().toHtmlEscaped(); - m_toolTip.append(contents); + m_toolTip = m_toolTip.isEmpty() ? helpContents : ("<p>" + m_toolTip + "</p><hr/><p>" + helpContents + "</p>"); } } } |