summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/clangcodemodel/clanghoverhandler.cpp115
-rw-r--r--src/plugins/clangcodemodel/clanghoverhandler.h1
-rw-r--r--src/plugins/cpptools/cpphoverhandler.cpp39
-rw-r--r--src/plugins/cpptools/cpphoverhandler.h1
-rw-r--r--src/plugins/texteditor/basehoverhandler.cpp8
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>");
}
}
}