summaryrefslogtreecommitdiff
path: root/src/plugins/clangcodemodel
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@qt.io>2018-01-12 12:29:43 +0100
committerNikolai Kosjar <nikolai.kosjar@qt.io>2018-01-16 15:32:15 +0000
commit76c25bcd6a97dda3921e8bc487e1c61f10938ad2 (patch)
tree7854480970b5290d9c3f225942c7780d355a2247 /src/plugins/clangcodemodel
parent7872ddde4cbaba2c6e5f55f1d05184ba33ba326b (diff)
downloadqt-creator-76c25bcd6a97dda3921e8bc487e1c61f10938ad2.tar.gz
Clang: Provide tooltips
This includes also the query data for the help system (F1) for an identifier under cursor. Regressions (libclang changes necessary): - Function signatures do not contain default values. - Aliases are not resolved for/at: - template types - qualified name of a type Fixes/Improvements: - Resolve "auto" - On a template type, show also the template parameter. - For a typedef like typedef long long superlong; the tooltip was "long long superlong", which was confusing. Now, "long long" is shown. New: - Show first or \brief paragraph of a documentation comment. - Show size of a class at definition. - Show size of a field member in class definition. Task-number: QTCREATORBUG-11259 Change-Id: Ie1a07930d0e882015d07dc43e35bb81a685cdeb8 Reviewed-by: Marco Bubke <marco.bubke@qt.io>
Diffstat (limited to 'src/plugins/clangcodemodel')
-rw-r--r--src/plugins/clangcodemodel/clangbackendcommunicator.cpp9
-rw-r--r--src/plugins/clangcodemodel/clangbackendcommunicator.h3
-rw-r--r--src/plugins/clangcodemodel/clangbackendreceiver.cpp78
-rw-r--r--src/plugins/clangcodemodel/clangbackendreceiver.h5
-rw-r--r--src/plugins/clangcodemodel/clangbackendsender.cpp7
-rw-r--r--src/plugins/clangcodemodel/clangbackendsender.h1
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel.pro2
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel.qbs2
-rw-r--r--src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp19
-rw-r--r--src/plugins/clangcodemodel/clangeditordocumentprocessor.h5
-rw-r--r--src/plugins/clangcodemodel/clanghoverhandler.cpp232
-rw-r--r--src/plugins/clangcodemodel/clanghoverhandler.h60
-rw-r--r--src/plugins/clangcodemodel/clangmodelmanagersupport.cpp4
13 files changed, 421 insertions, 6 deletions
diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp
index 5650479312..1abd6982ed 100644
--- a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp
+++ b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp
@@ -392,6 +392,15 @@ QFuture<CppTools::CursorInfo> BackendCommunicator::requestLocalReferences(
return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument);
}
+QFuture<CppTools::ToolTipInfo> BackendCommunicator::requestToolTip(
+ const FileContainer &fileContainer, quint32 line, quint32 column)
+{
+ const RequestToolTipMessage message(fileContainer, line, column);
+ m_sender->requestToolTip(message);
+
+ return m_receiver.addExpectedToolTipMessage(message.ticketNumber());
+}
+
QFuture<CppTools::SymbolInfo> BackendCommunicator::requestFollowSymbol(
const FileContainer &curFileContainer,
quint32 line,
diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.h b/src/plugins/clangcodemodel/clangbackendcommunicator.h
index bd7494a6c2..b3cb166a39 100644
--- a/src/plugins/clangcodemodel/clangbackendcommunicator.h
+++ b/src/plugins/clangcodemodel/clangbackendcommunicator.h
@@ -82,6 +82,9 @@ public:
quint32 line,
quint32 column,
QTextDocument *textDocument);
+ QFuture<CppTools::ToolTipInfo> requestToolTip(const FileContainer &fileContainer,
+ quint32 line,
+ quint32 column);
QFuture<CppTools::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer,
quint32 line,
quint32 column);
diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.cpp b/src/plugins/clangcodemodel/clangbackendreceiver.cpp
index 8d5ec92d00..f2606d74cc 100644
--- a/src/plugins/clangcodemodel/clangbackendreceiver.cpp
+++ b/src/plugins/clangcodemodel/clangbackendreceiver.cpp
@@ -128,6 +128,18 @@ QFuture<CppTools::SymbolInfo> BackendReceiver::addExpectedRequestFollowSymbolMes
return futureInterface.future();
}
+QFuture<CppTools::ToolTipInfo> BackendReceiver::addExpectedToolTipMessage(quint64 ticket)
+{
+ QTC_CHECK(!m_toolTipsTable.contains(ticket));
+
+ QFutureInterface<CppTools::ToolTipInfo> futureInterface;
+ futureInterface.reportStarted();
+
+ m_toolTipsTable.insert(ticket, futureInterface);
+
+ return futureInterface.future();
+}
+
bool BackendReceiver::isExpectingCodeCompletedMessage() const
{
return !m_assistProcessorsTable.isEmpty();
@@ -272,6 +284,72 @@ void BackendReceiver::references(const ReferencesMessage &message)
futureInterface.reportFinished();
}
+static TextEditor::HelpItem::Category toHelpItemCategory(ToolTipInfo::QdocCategory category)
+{
+ switch (category) {
+ case ToolTipInfo::Unknown:
+ return TextEditor::HelpItem::Unknown;
+ case ToolTipInfo::ClassOrNamespace:
+ return TextEditor::HelpItem::ClassOrNamespace;
+ case ToolTipInfo::Enum:
+ return TextEditor::HelpItem::Enum;
+ case ToolTipInfo::Typedef:
+ return TextEditor::HelpItem::Typedef;
+ case ToolTipInfo::Macro:
+ return TextEditor::HelpItem::Macro;
+ case ToolTipInfo::Brief:
+ return TextEditor::HelpItem::Brief;
+ case ToolTipInfo::Function:
+ return TextEditor::HelpItem::Function;
+ }
+
+ return TextEditor::HelpItem::Unknown;
+}
+
+static QStringList toStringList(const Utf8StringVector &utf8StringVector)
+{
+ QStringList list;
+ list.reserve(utf8StringVector.size());
+
+ for (const Utf8String &utf8String : utf8StringVector)
+ list << utf8String.toString();
+
+ return list;
+}
+
+static CppTools::ToolTipInfo toToolTipInfo(const ToolTipMessage &message)
+{
+ CppTools::ToolTipInfo info;
+
+ const ToolTipInfo backendInfo = message.toolTipInfo();
+
+ info.text = backendInfo.text();
+ info.briefComment = backendInfo.briefComment();
+
+ info.qDocIdCandidates = toStringList(backendInfo.qdocIdCandidates());
+ info.qDocMark = backendInfo.qdocMark();
+ info.qDocCategory = toHelpItemCategory(backendInfo.qdocCategory());
+
+ info.sizeInBytes = backendInfo.sizeInBytes();
+
+ return info;
+}
+
+void BackendReceiver::tooltip(const ToolTipMessage &message)
+{
+ qCDebugIpc() << "ToolTipMessage" << message.toolTipInfo().text();
+
+ const quint64 ticket = message.ticketNumber();
+ QFutureInterface<CppTools::ToolTipInfo> futureInterface = m_toolTipsTable.take(ticket);
+ QTC_CHECK(futureInterface != QFutureInterface<CppTools::ToolTipInfo>());
+
+ if (futureInterface.isCanceled())
+ return; // A new request was issued making this one outdated.
+
+ futureInterface.reportResult(toToolTipInfo(message));
+ futureInterface.reportFinished();
+}
+
void BackendReceiver::followSymbol(const ClangBackEnd::FollowSymbolMessage &message)
{
qCDebugIpc() << "FollowSymbolMessage with"
diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.h b/src/plugins/clangcodemodel/clangbackendreceiver.h
index d7a966eae9..921150a52d 100644
--- a/src/plugins/clangcodemodel/clangbackendreceiver.h
+++ b/src/plugins/clangcodemodel/clangbackendreceiver.h
@@ -27,6 +27,7 @@
#include <cpptools/cppcursorinfo.h>
#include <cpptools/cppsymbolinfo.h>
+#include <cpptools/baseeditordocumentprocessor.h>
#include <clangsupport/clangcodemodelclientinterface.h>
@@ -59,6 +60,7 @@ public:
const CppTools::SemanticInfo::LocalUseMap &localUses
= CppTools::SemanticInfo::LocalUseMap());
QFuture<CppTools::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket);
+ QFuture<CppTools::ToolTipInfo> addExpectedToolTipMessage(quint64 ticket);
bool isExpectingCodeCompletedMessage() const;
void reset();
@@ -70,6 +72,7 @@ private:
void documentAnnotationsChanged(const ClangBackEnd::DocumentAnnotationsChangedMessage &message) override;
void references(const ClangBackEnd::ReferencesMessage &message) override;
+ void tooltip(const ClangBackEnd::ToolTipMessage &message) override;
void followSymbol(const ClangBackEnd::FollowSymbolMessage &message) override;
private:
@@ -89,7 +92,7 @@ private:
CppTools::SemanticInfo::LocalUseMap localUses;
};
QHash<quint64, ReferencesEntry> m_referencesTable;
-
+ QHash<quint64, QFutureInterface<CppTools::ToolTipInfo>> m_toolTipsTable;
QHash<quint64, QFutureInterface<CppTools::SymbolInfo>> m_followTable;
};
diff --git a/src/plugins/clangcodemodel/clangbackendsender.cpp b/src/plugins/clangcodemodel/clangbackendsender.cpp
index 089377083f..f6f8aea1cf 100644
--- a/src/plugins/clangcodemodel/clangbackendsender.cpp
+++ b/src/plugins/clangcodemodel/clangbackendsender.cpp
@@ -120,6 +120,13 @@ void BackendSender::requestReferences(const RequestReferencesMessage &message)
m_connection->serverProxy().requestReferences(message);
}
+void BackendSender::requestToolTip(const RequestToolTipMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().requestToolTip(message);
+}
+
void BackendSender::requestFollowSymbol(const RequestFollowSymbolMessage &message)
{
QTC_CHECK(m_connection->isConnected());
diff --git a/src/plugins/clangcodemodel/clangbackendsender.h b/src/plugins/clangcodemodel/clangbackendsender.h
index ca9238ae65..f01326a4dc 100644
--- a/src/plugins/clangcodemodel/clangbackendsender.h
+++ b/src/plugins/clangcodemodel/clangbackendsender.h
@@ -48,6 +48,7 @@ public:
void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override;
void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) override;
+ void requestToolTip(const ClangBackEnd::RequestToolTipMessage &message) override;
void requestFollowSymbol(const ClangBackEnd::RequestFollowSymbolMessage &message) override;
void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) override;
diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro
index 9136db5db5..0e444a350e 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.pro
+++ b/src/plugins/clangcodemodel/clangcodemodel.pro
@@ -30,6 +30,7 @@ SOURCES += \
clangfixitoperationsextractor.cpp \
clangfollowsymbol.cpp \
clangfunctionhintmodel.cpp \
+ clanghoverhandler.cpp \
clangtokeninfosreporter.cpp \
clangmodelmanagersupport.cpp \
clangpreprocessorassistproposalitem.cpp \
@@ -66,6 +67,7 @@ HEADERS += \
clangfixitoperationsextractor.h \
clangfollowsymbol.h \
clangfunctionhintmodel.h \
+ clanghoverhandler.h \
clangisdiagnosticrelatedtolocation.h \
clangmodelmanagersupport.h \
clangpreprocessorassistproposalitem.h \
diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs
index cc81025925..90105b86d3 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.qbs
+++ b/src/plugins/clangcodemodel/clangcodemodel.qbs
@@ -80,6 +80,8 @@ QtcPlugin {
"clangfollowsymbol.h",
"clangfunctionhintmodel.cpp",
"clangfunctionhintmodel.h",
+ "clanghoverhandler.cpp",
+ "clanghoverhandler.h",
"clangtokeninfosreporter.cpp",
"clangtokeninfosreporter.h",
"clangisdiagnosticrelatedtolocation.h",
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
index 6eb98b2c92..a282350f24 100644
--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
@@ -375,6 +375,15 @@ ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column)
static_cast<quint32>(column));
}
+QFuture<CppTools::ToolTipInfo> ClangEditorDocumentProcessor::toolTipInfo(const QByteArray &codecName,
+ int line,
+ int column)
+{
+ return m_communicator.requestToolTip(simpleFileContainer(codecName),
+ static_cast<quint32>(line),
+ static_cast<quint32>(column));
+}
+
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const
{
return fileContainerWithArguments(m_projectPart.data());
@@ -480,13 +489,19 @@ ClangEditorDocumentProcessor::creatorForHeaderErrorDiagnosticWidget(
};
}
-ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer() const
+ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer(
+ const QByteArray &codecName) const
{
Utf8String projectPartId;
if (m_projectPart)
projectPartId = m_projectPart->id();
- return ClangBackEnd::FileContainer(filePath(), projectPartId, Utf8String(), false, revision());
+ return ClangBackEnd::FileContainer(filePath(),
+ projectPartId,
+ Utf8String(),
+ false,
+ revision(),
+ Utf8String::fromByteArray(codecName));
}
static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart)
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
index 2bb7ca0463..67745b582c 100644
--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
@@ -88,6 +88,9 @@ public:
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams &params) override;
QFuture<CppTools::CursorInfo> requestLocalReferences(const QTextCursor &cursor) override;
QFuture<CppTools::SymbolInfo> requestFollowSymbol(int line, int column) override;
+ QFuture<CppTools::ToolTipInfo> toolTipInfo(const QByteArray &codecName,
+ int line,
+ int column) override;
ClangBackEnd::FileContainer fileContainerWithArguments() const;
@@ -106,7 +109,7 @@ private:
void requestDocumentAnnotations(const QString &projectpartId);
HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget(
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic);
- ClangBackEnd::FileContainer simpleFileContainer() const;
+ ClangBackEnd::FileContainer simpleFileContainer(const QByteArray &codecName = QByteArray()) const;
ClangBackEnd::FileContainer fileContainerWithArguments(CppTools::ProjectPart *projectPart) const;
ClangBackEnd::FileContainer fileContainerWithArgumentsAndDocumentContent(
CppTools::ProjectPart *projectPart) const;
diff --git a/src/plugins/clangcodemodel/clanghoverhandler.cpp b/src/plugins/clangcodemodel/clanghoverhandler.cpp
new file mode 100644
index 0000000000..6610b555c2
--- /dev/null
+++ b/src/plugins/clangcodemodel/clanghoverhandler.cpp
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clanghoverhandler.h"
+
+#include <coreplugin/helpmanager.h>
+#include <cpptools/baseeditordocumentprocessor.h>
+#include <cpptools/cppmodelmanager.h>
+#include <cpptools/editordocumenthandle.h>
+#include <texteditor/texteditor.h>
+
+#include <utils/qtcassert.h>
+#include <utils/textutils.h>
+#include <utils/tooltip/tooltip.h>
+
+#include <QFutureWatcher>
+#include <QLoggingCategory>
+#include <QTextCodec>
+#include <QVBoxLayout>
+
+Q_LOGGING_CATEGORY(hoverLog, "qtc.clangcodemodel.hover");
+
+using namespace TextEditor;
+
+namespace ClangCodeModel {
+namespace Internal {
+
+static CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor(TextEditorWidget *editorWidget)
+{
+ const QString filePath = editorWidget->textDocument()->filePath().toString();
+ auto cppModelManager = CppTools::CppModelManager::instance();
+ CppTools::CppEditorDocumentHandle *editorHandle = cppModelManager->cppEditorDocument(filePath);
+
+ if (editorHandle)
+ return editorHandle->processor();
+
+ return 0;
+}
+
+static bool editorDocumentProcessorHasDiagnosticAt(TextEditorWidget *editorWidget, int pos)
+{
+ if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
+ int line, column;
+ if (Utils::Text::convertPosition(editorWidget->document(), pos, &line, &column))
+ return processor->hasDiagnosticsAt(line, column);
+ }
+
+ return false;
+}
+
+static void processWithEditorDocumentProcessor(TextEditorWidget *editorWidget,
+ const QPoint &point,
+ int position,
+ const QString &helpId)
+{
+ if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
+ int line, column;
+ if (Utils::Text::convertPosition(editorWidget->document(), position, &line, &column)) {
+ auto layout = new QVBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(2);
+ processor->addDiagnosticToolTipToLayout(line, column, layout);
+ Utils::ToolTip::show(point, layout, editorWidget, helpId);
+ }
+ }
+}
+
+static QFuture<CppTools::ToolTipInfo> editorDocumentHandlesToolTipInfo(
+ TextEditorWidget *editorWidget, int pos)
+{
+ const QByteArray textCodecName = editorWidget->textDocument()->codec()->name();
+ if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
+ int line, column;
+ if (Utils::Text::convertPosition(editorWidget->document(), pos, &line, &column))
+ return processor->toolTipInfo(textCodecName, line, column + 1);
+ }
+
+ return QFuture<CppTools::ToolTipInfo>();
+}
+
+ClangHoverHandler::ClangHoverHandler()
+{
+ setIsAsyncHandler(true);
+}
+
+ClangHoverHandler::~ClangHoverHandler()
+{
+ cancelAsyncCheck();
+}
+
+void ClangHoverHandler::identifyMatchAsync(TextEditorWidget *editorWidget,
+ int pos,
+ BaseHoverHandler::ReportPriority report)
+{
+ // Reset
+ m_futureWatcher.reset();
+ m_cursorPosition = -1;
+
+ // Check for diagnostics (sync)
+ if (editorDocumentProcessorHasDiagnosticAt(editorWidget, pos)) {
+ qCDebug(hoverLog) << "Checking for diagnostic at" << pos;
+ setPriority(Priority_Diagnostic);
+ m_cursorPosition = pos;
+ report(priority());
+ return;
+ }
+
+ // Check for tooltips (async)
+ QFuture<CppTools::ToolTipInfo> future = editorDocumentHandlesToolTipInfo(editorWidget, pos);
+ if (QTC_GUARD(future.isRunning())) {
+ 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]() {
+ processToolTipInfo(m_futureWatcher->result());
+ });
+ m_futureWatcher->setFuture(future);
+ return;
+ }
+
+ report(Priority_None); // Ops, something went wrong.
+}
+
+void ClangHoverHandler::cancelAsyncCheck()
+{
+ if (m_futureWatcher)
+ m_futureWatcher->cancel();
+}
+
+#define RETURN_TEXT_FOR_CASE(enumValue) case TextEditor::HelpItem::enumValue: return #enumValue
+static const char *helpItemCategoryAsString(TextEditor::HelpItem::Category category)
+{
+ switch (category) {
+ RETURN_TEXT_FOR_CASE(Unknown);
+ RETURN_TEXT_FOR_CASE(ClassOrNamespace);
+ RETURN_TEXT_FOR_CASE(Enum);
+ RETURN_TEXT_FOR_CASE(Typedef);
+ RETURN_TEXT_FOR_CASE(Macro);
+ RETURN_TEXT_FOR_CASE(Brief);
+ RETURN_TEXT_FOR_CASE(Function);
+ RETURN_TEXT_FOR_CASE(QmlComponent);
+ RETURN_TEXT_FOR_CASE(QmlProperty);
+ RETURN_TEXT_FOR_CASE(QMakeVariableOfFunction);
+ }
+
+ return "UnhandledHelpItemCategory";
+}
+#undef RETURN_TEXT_FOR_CASE
+
+void ClangHoverHandler::processToolTipInfo(const CppTools::ToolTipInfo &info)
+{
+ qCDebug(hoverLog) << "Processing tooltip info" << info.text;
+
+ QString text = info.text;
+ if (!info.briefComment.isEmpty())
+ text.append("\n\n" + info.briefComment);
+
+ for (const QString &qdocIdCandidate : info.qDocIdCandidates) {
+ qCDebug(hoverLog) << "Querying help manager with"
+ << qdocIdCandidate
+ << info.qDocMark
+ << helpItemCategoryAsString(info.qDocCategory);
+ const QMap<QString, QUrl> helpLinks = Core::HelpManager::linksForIdentifier(qdocIdCandidate);
+ if (!helpLinks.isEmpty()) {
+ qCDebug(hoverLog) << " Match!";
+ setLastHelpItemIdentified(
+ HelpItem(qdocIdCandidate, info.qDocMark, info.qDocCategory, helpLinks));
+ break;
+ }
+ }
+
+ if (!info.sizeInBytes.isEmpty())
+ text.append(tr("\n\n%1 bytes").arg(info.sizeInBytes));
+
+ setToolTip(text);
+ 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)
+{
+ if (priority() == Priority_Diagnostic) {
+ const HelpItem helpItem = lastHelpItemIdentified();
+ const QString helpId = helpItem.isValid() ? helpItem.helpId() : QString();
+ processWithEditorDocumentProcessor(editorWidget, point, m_cursorPosition, helpId);
+ return;
+ }
+
+ // Priority_Tooltip / Priority_Help
+ BaseHoverHandler::operateTooltip(editorWidget, point);
+}
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clanghoverhandler.h b/src/plugins/clangcodemodel/clanghoverhandler.h
new file mode 100644
index 0000000000..85b7999f94
--- /dev/null
+++ b/src/plugins/clangcodemodel/clanghoverhandler.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <cpptools/baseeditordocumentprocessor.h>
+#include <cpptools/cpphoverhandler.h>
+#include <texteditor/basehoverhandler.h>
+
+namespace ClangCodeModel {
+namespace Internal {
+
+class ClangHoverHandler : public TextEditor::BaseHoverHandler
+{
+ Q_DECLARE_TR_FUNCTIONS(ClangHoverHandler)
+
+public:
+ ClangHoverHandler();
+ ~ClangHoverHandler() override;
+
+ void identifyMatchAsync(TextEditor::TextEditorWidget *editorWidget,
+ int pos,
+ ReportPriority report) override;
+ void decorateToolTip() override;
+ void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override;
+
+private:
+ void cancelAsyncCheck() override;
+ void processToolTipInfo(const CppTools::ToolTipInfo &info);
+
+private:
+ int m_cursorPosition = -1;
+ QScopedPointer<QFutureWatcher<CppTools::ToolTipInfo>> m_futureWatcher;
+ ReportPriority m_reportPriority;
+};
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
index 9271975dfd..9495e6d5eb 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
@@ -29,11 +29,11 @@
#include "clangeditordocumentprocessor.h"
#include "clangutils.h"
#include "clangfollowsymbol.h"
+#include "clanghoverhandler.h"
#include "clangrefactoringengine.h"
#include <coreplugin/editormanager/editormanager.h>
#include <cpptools/cppfollowsymbolundercursor.h>
-#include <cpptools/cpphoverhandler.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/editordocumenthandle.h>
#include <cpptools/projectinfo.h>
@@ -114,7 +114,7 @@ CppTools::CppCompletionAssistProvider *ModelManagerSupportClang::completionAssis
TextEditor::BaseHoverHandler *ModelManagerSupportClang::createHoverHandler()
{
- return new CppTools::CppHoverHandler;
+ return new Internal::ClangHoverHandler;
}
CppTools::FollowSymbolInterface &ModelManagerSupportClang::followSymbolInterface()