forked from qt-creator/qt-creator
LanguageClient: add hover handler
Change-Id: Iddf30828ef26a157ab935d0abe708087ab123dd6 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -58,19 +58,14 @@ Utils::optional<QList<MarkupKind>>
|
||||
TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities::
|
||||
documentationFormat() const
|
||||
{
|
||||
Utils::optional<QList<int>> array = optionalArray<int>(documentationFormatKey);
|
||||
if (!array)
|
||||
return Utils::nullopt;
|
||||
return Utils::make_optional(Utils::transform(array.value(), [] (int value) {
|
||||
return static_cast<MarkupKind>(value);
|
||||
}));
|
||||
return optionalArray<MarkupKind>(documentationFormatKey);
|
||||
}
|
||||
|
||||
void
|
||||
TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities::
|
||||
setDocumentationFormat(const QList<MarkupKind> &documentationFormat)
|
||||
{
|
||||
insert(documentationFormatKey, enumArrayToJsonArray<MarkupKind>(documentationFormat));
|
||||
insertArray(documentationFormatKey, documentationFormat);
|
||||
}
|
||||
|
||||
TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemKindCapabilities::CompletionItemKindCapabilities()
|
||||
@@ -107,36 +102,26 @@ setValueSet(const QList<CompletionItemKind::Kind> &valueSet)
|
||||
|
||||
Utils::optional<QList<MarkupKind> > TextDocumentClientCapabilities::HoverCapabilities::contentFormat() const
|
||||
{
|
||||
Utils::optional<QList<int>> array = optionalArray<int>(contentFormatKey);
|
||||
if (!array)
|
||||
return Utils::nullopt;
|
||||
return Utils::make_optional(Utils::transform(array.value(), [] (int value) {
|
||||
return static_cast<MarkupKind>(value);
|
||||
}));
|
||||
return optionalArray<MarkupKind>(contentFormatKey);
|
||||
}
|
||||
|
||||
void TextDocumentClientCapabilities::HoverCapabilities::setContentFormat(const QList<MarkupKind> &contentFormat)
|
||||
{
|
||||
insert(contentFormatKey, enumArrayToJsonArray<MarkupKind>(contentFormat));
|
||||
insertArray(contentFormatKey, contentFormat);
|
||||
}
|
||||
|
||||
Utils::optional<QList<MarkupKind>>
|
||||
TextDocumentClientCapabilities::SignatureHelpCapabilities::SignatureInformationCapabilities::
|
||||
documentationFormat() const
|
||||
{
|
||||
Utils::optional<QList<int>> array = optionalArray<int>(documentationFormatKey);
|
||||
if (!array)
|
||||
return Utils::nullopt;
|
||||
return Utils::make_optional(Utils::transform(array.value(), [] (int value) {
|
||||
return static_cast<MarkupKind>(value);
|
||||
}));
|
||||
return optionalArray<MarkupKind>(documentationFormatKey);
|
||||
}
|
||||
|
||||
void
|
||||
TextDocumentClientCapabilities::SignatureHelpCapabilities::SignatureInformationCapabilities::
|
||||
setDocumentationFormat(const QList<MarkupKind> &documentationFormat)
|
||||
{
|
||||
insert(documentationFormatKey, enumArrayToJsonArray<MarkupKind>(documentationFormat));
|
||||
insertArray(documentationFormatKey, documentationFormat);
|
||||
}
|
||||
|
||||
InitializeParams::InitializeParams()
|
||||
|
||||
@@ -69,6 +69,7 @@ constexpr char contentChangesKey[] = "contentChanges";
|
||||
constexpr char contentCharsetName[] = "charset";
|
||||
constexpr char contentFormatKey[] = "contentFormat";
|
||||
constexpr char contentKey[] = "value";
|
||||
constexpr char contentsKey[] = "contents";
|
||||
constexpr char contentLengthFieldName[] = "Content-Length";
|
||||
constexpr char contentTypeFieldName[] = "Content-Type";
|
||||
constexpr char contextKey[] = "context";
|
||||
|
||||
@@ -49,19 +49,19 @@ constexpr const char DocumentOnTypeFormattingRequest::methodName[];
|
||||
constexpr const char RenameRequest::methodName[];
|
||||
constexpr const char SignatureHelpRequest::methodName[];
|
||||
|
||||
MarkedString LanguageServerProtocol::Hover::content() const
|
||||
HoverContent LanguageServerProtocol::Hover::content() const
|
||||
{
|
||||
return MarkedString(value(contentKey));
|
||||
return HoverContent(value(contentsKey));
|
||||
}
|
||||
|
||||
void Hover::setContent(const MarkedString &content)
|
||||
void Hover::setContent(const HoverContent &content)
|
||||
{
|
||||
if (auto val = Utils::get_if<MarkedLanguageString>(&content))
|
||||
insert(contentKey, *val);
|
||||
if (auto val = Utils::get_if<MarkedString>(&content))
|
||||
insert(contentsKey, *val);
|
||||
else if (auto val = Utils::get_if<MarkupContent>(&content))
|
||||
insert(contentKey, *val);
|
||||
else if (auto val = Utils::get_if<QList<MarkedLanguageString>>(&content))
|
||||
insert(contentKey, LanguageClientArray<MarkedLanguageString>(*val).toJson());
|
||||
insert(contentsKey, *val);
|
||||
else if (auto val = Utils::get_if<QList<MarkedString>>(&content))
|
||||
insert(contentsKey, LanguageClientArray<MarkedString>(*val).toJson());
|
||||
else
|
||||
QTC_ASSERT_STRING("LanguageClient Using unknown type Hover::setContent");
|
||||
}
|
||||
@@ -333,32 +333,53 @@ DocumentHighlightsResult::DocumentHighlightsResult(const QJsonValue &value)
|
||||
}
|
||||
|
||||
MarkedString::MarkedString(const QJsonValue &value)
|
||||
{
|
||||
if (value.isObject()) {
|
||||
MarkedLanguageString string(value.toObject());
|
||||
if (string.isValid(nullptr))
|
||||
emplace<MarkedLanguageString>(string);
|
||||
} else if (value.isString()) {
|
||||
emplace<QString>(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
LanguageServerProtocol::MarkedString::operator const QJsonValue() const
|
||||
{
|
||||
if (auto val = Utils::get_if<QString>(this))
|
||||
return *val;
|
||||
if (auto val = Utils::get_if<MarkedLanguageString>(this))
|
||||
return QJsonValue(*val);
|
||||
return {};
|
||||
}
|
||||
|
||||
HoverContent::HoverContent(const QJsonValue &value)
|
||||
{
|
||||
if (value.isArray()) {
|
||||
emplace<QList<MarkedLanguageString>>(
|
||||
LanguageClientArray<MarkedLanguageString>(value).toList());
|
||||
emplace<QList<MarkedString>>(LanguageClientArray<MarkedString>(value).toList());
|
||||
} else if (value.isObject()) {
|
||||
const QJsonObject &object = value.toObject();
|
||||
MarkedLanguageString markedLanguageString(object);
|
||||
if (markedLanguageString.isValid(nullptr))
|
||||
emplace<MarkedLanguageString>(markedLanguageString);
|
||||
emplace<MarkedString>(markedLanguageString);
|
||||
else
|
||||
emplace<MarkupContent>(MarkupContent(object));
|
||||
} else if (value.isString()) {
|
||||
emplace<MarkedString>(MarkedString(value.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
bool MarkedString::isValid(QStringList *errorHierarchy) const
|
||||
bool HoverContent::isValid(QStringList *errorHierarchy) const
|
||||
{
|
||||
if (Utils::holds_alternative<MarkedLanguageString>(*this)
|
||||
if (Utils::holds_alternative<MarkedString>(*this)
|
||||
|| Utils::holds_alternative<MarkupContent>(*this)
|
||||
|| Utils::holds_alternative<QList<MarkedLanguageString>>(*this)) {
|
||||
|| Utils::holds_alternative<QList<MarkedString>>(*this)) {
|
||||
return true;
|
||||
}
|
||||
if (errorHierarchy) {
|
||||
*errorHierarchy << QCoreApplication::translate(
|
||||
"LanguageServerProtocol::MarkedString",
|
||||
"MarkedString should be either MarkedLanguageString, "
|
||||
"MarkupContent, or QList<MarkedLanguageString>.");
|
||||
"LanguageServerProtocol::HoverContent",
|
||||
"HoverContent should be either MarkedString, "
|
||||
"MarkupContent, or QList<MarkedString>.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -58,14 +58,31 @@ public:
|
||||
{ return check<QString>(error, languageKey) && check<QString>(error, valueKey); }
|
||||
};
|
||||
|
||||
class MarkedString : public Utils::variant<MarkedLanguageString, QList<MarkedLanguageString>, MarkupContent>
|
||||
class LANGUAGESERVERPROTOCOL_EXPORT MarkedString
|
||||
: public Utils::variant<QString, MarkedLanguageString>
|
||||
{
|
||||
public:
|
||||
MarkedString() = default;
|
||||
explicit MarkedString(const MarkedLanguageString &other) : variant(other) {}
|
||||
explicit MarkedString(const QList<MarkedLanguageString> &other) : variant(other) {}
|
||||
explicit MarkedString(const MarkupContent &other) : variant(other) {}
|
||||
explicit MarkedString(const MarkedLanguageString &other)
|
||||
: variant(other)
|
||||
{}
|
||||
explicit MarkedString(const QString &other)
|
||||
: variant(other)
|
||||
{}
|
||||
explicit MarkedString(const QJsonValue &value);
|
||||
|
||||
operator const QJsonValue() const;
|
||||
};
|
||||
|
||||
class LANGUAGESERVERPROTOCOL_EXPORT HoverContent
|
||||
: public Utils::variant<MarkedString, QList<MarkedString>, MarkupContent>
|
||||
{
|
||||
public:
|
||||
HoverContent() = default;
|
||||
explicit HoverContent(const MarkedString &other) : variant(other) {}
|
||||
explicit HoverContent(const QList<MarkedString> &other) : variant(other) {}
|
||||
explicit HoverContent(const MarkupContent &other) : variant(other) {}
|
||||
explicit HoverContent(const QJsonValue &value);
|
||||
bool isValid(QStringList *errorHierarchy) const;
|
||||
};
|
||||
|
||||
@@ -74,15 +91,15 @@ class LANGUAGESERVERPROTOCOL_EXPORT Hover : public JsonObject
|
||||
public:
|
||||
using JsonObject::JsonObject;
|
||||
|
||||
MarkedString content() const;
|
||||
void setContent(const MarkedString &content);
|
||||
HoverContent content() const;
|
||||
void setContent(const HoverContent &content);
|
||||
|
||||
Utils::optional<Range> range() const { return optionalValue<Range>(rangeKey); }
|
||||
void setRange(const Range &range) { insert(rangeKey, range); }
|
||||
void clearRange() { remove(rangeKey); }
|
||||
|
||||
bool isValid(QStringList *error) const override
|
||||
{ return check<MarkedString>(error, contentKey) && checkOptional<Range>(error, rangeKey); }
|
||||
{ return check<HoverContent>(error, contentsKey) && checkOptional<Range>(error, rangeKey); }
|
||||
};
|
||||
|
||||
class LANGUAGESERVERPROTOCOL_EXPORT HoverRequest
|
||||
|
||||
@@ -415,4 +415,20 @@ Utils::FileName DocumentUri::toFileName() const
|
||||
: Utils::FileName();
|
||||
}
|
||||
|
||||
MarkupKind::MarkupKind(const QJsonValue &value)
|
||||
{
|
||||
m_value = value.toString() == "markdown" ? markdown : plaintext;
|
||||
}
|
||||
|
||||
LanguageServerProtocol::MarkupKind::operator const QJsonValue() const
|
||||
{
|
||||
switch (m_value) {
|
||||
case MarkupKind::markdown:
|
||||
return "markdown";
|
||||
case MarkupKind::plaintext:
|
||||
return "plaintext";
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace LanguageServerProtocol
|
||||
|
||||
@@ -378,10 +378,24 @@ public:
|
||||
bool isValid(QStringList *error) const override;
|
||||
};
|
||||
|
||||
enum class MarkupKind
|
||||
class LANGUAGESERVERPROTOCOL_EXPORT MarkupKind
|
||||
{
|
||||
plaintext,
|
||||
markdown,
|
||||
public:
|
||||
enum Value { plaintext, markdown };
|
||||
MarkupKind() = default;
|
||||
MarkupKind(const Value value)
|
||||
: m_value(value)
|
||||
{}
|
||||
MarkupKind(const QJsonValue &value);
|
||||
|
||||
operator const QJsonValue() const;
|
||||
Value value() const { return m_value; }
|
||||
|
||||
bool operator==(const Value &value) const { return m_value == value; }
|
||||
|
||||
bool isValid(void *) const { return true; }
|
||||
private:
|
||||
Value m_value = plaintext;
|
||||
};
|
||||
|
||||
class LANGUAGESERVERPROTOCOL_EXPORT MarkupContent : public JsonObject
|
||||
@@ -390,15 +404,15 @@ public:
|
||||
using JsonObject::JsonObject;
|
||||
|
||||
// The type of the Markup
|
||||
MarkupKind kind() const { return static_cast<MarkupKind>(typedValue<int>(kindKey)); }
|
||||
void setKind(MarkupKind kind) { insert(kindKey, static_cast<int>(kind)); }
|
||||
MarkupKind kind() const { return value(kindKey); }
|
||||
void setKind(MarkupKind kind) { insert(kindKey, kind); }
|
||||
|
||||
// The content itself
|
||||
QString content() const { return typedValue<QString>(contentKey); }
|
||||
void setContent(const QString &content) { insert(contentKey, content); }
|
||||
|
||||
bool isValid(QStringList *error) const override
|
||||
{ return check<int>(error, kindKey) && check<QString>(error, contentKey); }
|
||||
{ return check<MarkupKind>(error, kindKey) && check<QString>(error, contentKey); }
|
||||
};
|
||||
|
||||
class LANGUAGESERVERPROTOCOL_EXPORT MarkupOrString : public Utils::variant<QString, MarkupContent>
|
||||
|
||||
@@ -96,6 +96,7 @@ Client::Client(BaseClientInterface *clientInterface)
|
||||
, m_quickFixProvider(this)
|
||||
, m_clientInterface(clientInterface)
|
||||
, m_documentSymbolCache(this)
|
||||
, m_hoverHandler(this)
|
||||
{
|
||||
m_contentHandler.insert(JsonRpcMessageHandler::jsonRpcMimeType(),
|
||||
&JsonRpcMessageHandler::parseContent);
|
||||
@@ -129,6 +130,7 @@ Client::~Client()
|
||||
if (auto textEditor = qobject_cast<BaseTextEditor *>(editor)) {
|
||||
TextEditorWidget *widget = textEditor->editorWidget();
|
||||
widget->setRefactorMarkers(RefactorMarker::filterOutType(widget->refactorMarkers(), id()));
|
||||
widget->removeHoverHandler(&m_hoverHandler);
|
||||
}
|
||||
}
|
||||
for (const DocumentUri &uri : m_diagnostics.keys())
|
||||
@@ -204,6 +206,12 @@ static ClientCapabilities generateClientCapabilities()
|
||||
CodeActionKind(QList<QString>{"*"}));
|
||||
codeActionCapabilities.setCodeActionLiteralSupport(literalSupport);
|
||||
documentCapabilities.setCodeAction(codeActionCapabilities);
|
||||
|
||||
TextDocumentClientCapabilities::HoverCapabilities hover;
|
||||
hover.setContentFormat({MarkupKind::plaintext});
|
||||
hover.setDynamicRegistration(true);
|
||||
documentCapabilities.setHover(hover);
|
||||
|
||||
documentCapabilities.setReferences(allowDynamicRegistration);
|
||||
documentCapabilities.setDocumentHighlight(allowDynamicRegistration);
|
||||
documentCapabilities.setDefinition(allowDynamicRegistration);
|
||||
@@ -915,6 +923,11 @@ DocumentSymbolCache *Client::documentSymbolCache()
|
||||
return &m_documentSymbolCache;
|
||||
}
|
||||
|
||||
HoverHandler *Client::hoverHandler()
|
||||
{
|
||||
return &m_hoverHandler;
|
||||
}
|
||||
|
||||
void Client::log(const ShowMessageParams &message,
|
||||
Core::MessageManager::PrintToOutputPaneFlag flag)
|
||||
{
|
||||
@@ -1113,6 +1126,10 @@ void Client::intializeCallback(const InitializeRequest::Response &initResponse)
|
||||
updateEditorToolBar(editor);
|
||||
}
|
||||
}
|
||||
for (Core::IEditor *editor : Core::DocumentModel::editorsForOpenedDocuments()) {
|
||||
if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor))
|
||||
textEditor->editorWidget()->addHoverHandler(&m_hoverHandler);
|
||||
}
|
||||
emit initialized(m_serverCapabilities);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "languageclientcompletionassist.h"
|
||||
#include "languageclientquickfix.h"
|
||||
#include "languageclientsettings.h"
|
||||
#include "languageclienthoverhandler.h"
|
||||
|
||||
#include <coreplugin/id.h>
|
||||
#include <coreplugin/messagemanager.h>
|
||||
@@ -155,6 +156,7 @@ public:
|
||||
const DynamicCapabilities &dynamicCapabilities() const;
|
||||
const BaseClientInterface *clientInterface() const;
|
||||
DocumentSymbolCache *documentSymbolCache();
|
||||
HoverHandler *hoverHandler();
|
||||
|
||||
signals:
|
||||
void initialized(LanguageServerProtocol::ServerCapabilities capabilities);
|
||||
@@ -205,6 +207,7 @@ private:
|
||||
QScopedPointer<BaseClientInterface> m_clientInterface;
|
||||
QMap<LanguageServerProtocol::DocumentUri, QList<TextMark *>> m_diagnostics;
|
||||
DocumentSymbolCache m_documentSymbolCache;
|
||||
HoverHandler m_hoverHandler;
|
||||
const ProjectExplorer::Project *m_project = nullptr;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ HEADERS += \
|
||||
dynamiccapabilities.h \
|
||||
languageclient_global.h \
|
||||
languageclientcompletionassist.h \
|
||||
languageclienthoverhandler.h \
|
||||
languageclientinterface.h \
|
||||
languageclientmanager.h \
|
||||
languageclientoutline.h \
|
||||
@@ -23,6 +24,7 @@ SOURCES += \
|
||||
documentsymbolcache.cpp \
|
||||
dynamiccapabilities.cpp \
|
||||
languageclientcompletionassist.cpp \
|
||||
languageclienthoverhandler.cpp \
|
||||
languageclientinterface.cpp \
|
||||
languageclientmanager.cpp \
|
||||
languageclientoutline.cpp \
|
||||
|
||||
@@ -22,6 +22,8 @@ QtcPlugin {
|
||||
"dynamiccapabilities.h",
|
||||
"languageclient.qrc",
|
||||
"languageclient_global.h",
|
||||
"languageclienthoverhandler.cpp",
|
||||
"languageclienthoverhandler.h",
|
||||
"languageclientinterface.cpp",
|
||||
"languageclientinterface.h",
|
||||
"languageclientcompletionassist.cpp",
|
||||
|
||||
148
src/plugins/languageclient/languageclienthoverhandler.cpp
Normal file
148
src/plugins/languageclient/languageclienthoverhandler.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 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 "languageclienthoverhandler.h"
|
||||
|
||||
#include "client.h"
|
||||
|
||||
#include <texteditor/textdocument.h>
|
||||
#include <texteditor/texteditor.h>
|
||||
#include <utils/mimetypes/mimedatabase.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/tooltip/tooltip.h>
|
||||
|
||||
using namespace LanguageServerProtocol;
|
||||
|
||||
namespace LanguageClient {
|
||||
|
||||
HoverHandler::HoverHandler(Client *client)
|
||||
: m_client(client)
|
||||
{}
|
||||
|
||||
HoverHandler::~HoverHandler()
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void HoverHandler::abort()
|
||||
{
|
||||
if (m_client && m_client->reachable() && m_currentRequest.has_value())
|
||||
m_client->cancelRequest(*m_currentRequest);
|
||||
m_currentRequest.reset();
|
||||
}
|
||||
|
||||
void HoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget,
|
||||
int pos,
|
||||
TextEditor::BaseHoverHandler::ReportPriority report)
|
||||
{
|
||||
if (m_currentRequest.has_value())
|
||||
abort();
|
||||
if (m_client.isNull()
|
||||
|| !m_client->documentOpen(editorWidget->textDocument())
|
||||
|| !m_client->capabilities().hoverProvider().value_or(false)) {
|
||||
report(Priority_None);
|
||||
return;
|
||||
}
|
||||
|
||||
bool sendMessage = m_client->capabilities().hoverProvider().value_or(false);
|
||||
if (Utils::optional<bool> registered = m_client->dynamicCapabilities().isRegistered(
|
||||
HoverRequest::methodName)) {
|
||||
sendMessage = registered.value();
|
||||
if (sendMessage) {
|
||||
const TextDocumentRegistrationOptions option(
|
||||
m_client->dynamicCapabilities().option(HoverRequest::methodName).toObject());
|
||||
if (option.isValid(nullptr)) {
|
||||
sendMessage = option.filterApplies(editorWidget->textDocument()->filePath(),
|
||||
Utils::mimeTypeForName(
|
||||
editorWidget->textDocument()->mimeType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!sendMessage) {
|
||||
report(Priority_None);
|
||||
return;
|
||||
}
|
||||
|
||||
m_report = report;
|
||||
auto uri = DocumentUri::fromFileName(editorWidget->textDocument()->filePath());
|
||||
QTextCursor cursor = editorWidget->textCursor();
|
||||
cursor.setPosition(pos);
|
||||
TextDocumentPositionParams params(uri, Position(cursor));
|
||||
HoverRequest request(params);
|
||||
request.setResponseCallback(
|
||||
[this](const HoverRequest::Response &response) { handleResponse(response); });
|
||||
m_client->sendContent(request);
|
||||
}
|
||||
|
||||
void HoverHandler::operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point)
|
||||
{
|
||||
if (toolTip().isEmpty())
|
||||
Utils::ToolTip::hide();
|
||||
else
|
||||
Utils::ToolTip::show(point, toolTip(), editorWidget);
|
||||
}
|
||||
|
||||
void HoverHandler::handleResponse(const HoverRequest::Response &response)
|
||||
{
|
||||
m_currentRequest.reset();
|
||||
if (Utils::optional<HoverRequest::Response::Error> error = response.error()) {
|
||||
if (m_client)
|
||||
m_client->log(error.value());
|
||||
}
|
||||
if (Utils::optional<Hover> result = response.result())
|
||||
setContent(result.value().content());
|
||||
m_report(priority());
|
||||
}
|
||||
|
||||
static QString toolTipForMarkedStrings(const QList<MarkedString> &markedStrings)
|
||||
{
|
||||
QString tooltip;
|
||||
for (const MarkedString &markedString : markedStrings) {
|
||||
if (!tooltip.isEmpty())
|
||||
tooltip += '\n';
|
||||
if (auto string = Utils::get_if<QString>(&markedString))
|
||||
tooltip += *string;
|
||||
else if (auto string = Utils::get_if<MarkedLanguageString>(&markedString))
|
||||
tooltip += string->value() + " [" + string->language() + ']';
|
||||
}
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
void HoverHandler::setContent(const HoverContent &hoverContent)
|
||||
{
|
||||
if (auto markupContent = Utils::get_if<MarkupContent>(&hoverContent)) {
|
||||
const QString &content = markupContent->content();
|
||||
if (markupContent->kind() == MarkupKind::plaintext)
|
||||
setToolTip(content);
|
||||
else if (m_client)
|
||||
m_client->log(tr("Got unsupported markup hover content: ") + content);
|
||||
} else if (auto markedString = Utils::get_if<MarkedString>(&hoverContent)) {
|
||||
setToolTip(toolTipForMarkedStrings({*markedString}));
|
||||
} else if (auto markedStrings = Utils::get_if<QList<MarkedString>>(&hoverContent)) {
|
||||
setToolTip(toolTipForMarkedStrings(*markedStrings));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace LanguageClient
|
||||
59
src/plugins/languageclient/languageclienthoverhandler.h
Normal file
59
src/plugins/languageclient/languageclienthoverhandler.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 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 <languageserverprotocol/languagefeatures.h>
|
||||
#include <texteditor/basehoverhandler.h>
|
||||
|
||||
namespace LanguageClient {
|
||||
|
||||
class Client;
|
||||
|
||||
class HoverHandler : public TextEditor::BaseHoverHandler
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(HoverHandler)
|
||||
public:
|
||||
explicit HoverHandler(Client *client);
|
||||
~HoverHandler() override;
|
||||
|
||||
void abort() override;
|
||||
|
||||
protected:
|
||||
void identifyMatch(TextEditor::TextEditorWidget *editorWidget,
|
||||
int pos,
|
||||
ReportPriority report) override;
|
||||
void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override;
|
||||
|
||||
private:
|
||||
void handleResponse(const LanguageServerProtocol::HoverRequest::Response &response);
|
||||
void setContent(const LanguageServerProtocol::HoverContent &content);
|
||||
|
||||
QPointer<Client> m_client;
|
||||
Utils::optional<LanguageServerProtocol::MessageId> m_currentRequest;
|
||||
TextEditor::BaseHoverHandler::ReportPriority m_report;
|
||||
};
|
||||
|
||||
} // namespace LanguageClient
|
||||
@@ -362,6 +362,8 @@ void LanguageClientManager::editorOpened(Core::IEditor *editor)
|
||||
});
|
||||
});
|
||||
updateEditorToolBar(editor);
|
||||
for (auto client : reachableClients())
|
||||
widget->addHoverHandler(client->hoverHandler());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5822,6 +5822,11 @@ void TextEditorWidget::addHoverHandler(BaseHoverHandler *handler)
|
||||
d->m_hoverHandlers.append(handler);
|
||||
}
|
||||
|
||||
void TextEditorWidget::removeHoverHandler(BaseHoverHandler *handler)
|
||||
{
|
||||
d->m_hoverHandlers.removeAll(handler);
|
||||
}
|
||||
|
||||
void TextEditorWidget::extraAreaLeaveEvent(QEvent *)
|
||||
{
|
||||
d->extraAreaPreviousMarkTooltipRequestedLine = -1;
|
||||
|
||||
@@ -474,6 +474,9 @@ public:
|
||||
|
||||
Core::HighlightScrollBarController *highlightScrollBarController() const;
|
||||
|
||||
void addHoverHandler(BaseHoverHandler *handler);
|
||||
void removeHoverHandler(BaseHoverHandler *handler);
|
||||
|
||||
signals:
|
||||
void assistFinished(); // Used in tests.
|
||||
void readOnlyChanged();
|
||||
@@ -534,8 +537,6 @@ protected:
|
||||
virtual void finalizeInitializationAfterDuplication(TextEditorWidget *) {}
|
||||
static QTextCursor flippedCursor(const QTextCursor &cursor);
|
||||
|
||||
void addHoverHandler(BaseHoverHandler *handler);
|
||||
|
||||
public:
|
||||
QString selectedText() const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user