diff options
Diffstat (limited to 'src/libs/languageserverprotocol')
20 files changed, 205 insertions, 158 deletions
diff --git a/src/libs/languageserverprotocol/CMakeLists.txt b/src/libs/languageserverprotocol/CMakeLists.txt new file mode 100644 index 0000000000..9ad446817f --- /dev/null +++ b/src/libs/languageserverprotocol/CMakeLists.txt @@ -0,0 +1,23 @@ +add_qtc_library(LanguageServerProtocol + DEPENDS Utils + SOURCES + basemessage.cpp basemessage.h + client.cpp client.h + clientcapabilities.cpp clientcapabilities.h + completion.cpp completion.h + diagnostics.cpp diagnostics.h + icontent.h + initializemessages.cpp initializemessages.h + jsonkeys.h + jsonobject.cpp jsonobject.h + jsonrpcmessages.cpp jsonrpcmessages.h + languagefeatures.cpp languagefeatures.h + languageserverprotocol_global.h + lsptypes.cpp lsptypes.h + lsputils.cpp lsputils.h + messages.cpp messages.h + servercapabilities.cpp servercapabilities.h + shutdownmessages.cpp shutdownmessages.h + textsynchronization.cpp textsynchronization.h + workspace.cpp workspace.h +) diff --git a/src/libs/languageserverprotocol/basemessage.cpp b/src/libs/languageserverprotocol/basemessage.cpp index 1ee17e3eee..950976549e 100644 --- a/src/libs/languageserverprotocol/basemessage.cpp +++ b/src/libs/languageserverprotocol/basemessage.cpp @@ -37,6 +37,8 @@ namespace LanguageServerProtocol { +Q_LOGGING_CATEGORY(parseLog, "qtc.languageserverprotocol.parse", QtWarningMsg) + BaseMessage::BaseMessage() : mimeType(JsonRpcMessageHandler::jsonRpcMimeType()) { } @@ -68,8 +70,7 @@ bool BaseMessage::operator==(const BaseMessage &other) const return true; } -static QPair<QByteArray, QByteArray> splitHeaderFieldLine( - const QByteArray &headerFieldLine, QString &parseError) +static QPair<QByteArray, QByteArray> splitHeaderFieldLine(const QByteArray &headerFieldLine) { static const int fieldSeparatorLength = int(std::strlen(headerFieldSeparator)); int assignmentIndex = headerFieldLine.indexOf(headerFieldSeparator); @@ -77,8 +78,7 @@ static QPair<QByteArray, QByteArray> splitHeaderFieldLine( return {headerFieldLine.mid(0, assignmentIndex), headerFieldLine.mid(assignmentIndex + fieldSeparatorLength)}; } - parseError = BaseMessage::tr("Unexpected header line \"%1\".") - .arg(QLatin1String(headerFieldLine)); + qCWarning(parseLog) << "Unexpected header line:" << QLatin1String(headerFieldLine); return {}; } @@ -134,8 +134,7 @@ void BaseMessage::parse(QBuffer *data, QString &parseError, BaseMessage &message message.content = data->read(message.contentLength); return; } - const QPair<QByteArray, QByteArray> nameAndValue = - splitHeaderFieldLine(headerFieldLine, parseError); + const QPair<QByteArray, QByteArray> nameAndValue = splitHeaderFieldLine(headerFieldLine); const QByteArray &headerFieldName = nameAndValue.first.trimmed(); const QByteArray &headerFieldValue = nameAndValue.second.trimmed(); @@ -146,9 +145,8 @@ void BaseMessage::parse(QBuffer *data, QString &parseError, BaseMessage &message } else if (headerFieldName == contentTypeFieldName) { parseContentType(message, headerFieldValue, parseError); } else { - parseError = tr("Unexpected header field \"%1\" in \"%2\".") - .arg(QLatin1String(headerFieldName), - QLatin1String(headerFieldLine)); + qCWarning(parseLog) << "Unexpected header field" << QLatin1String(headerFieldName) + << "in" << QLatin1String(headerFieldLine); } } diff --git a/src/libs/languageserverprotocol/basemessage.h b/src/libs/languageserverprotocol/basemessage.h index ba8238291a..b2835aa7d7 100644 --- a/src/libs/languageserverprotocol/basemessage.h +++ b/src/libs/languageserverprotocol/basemessage.h @@ -31,6 +31,7 @@ #include <QByteArray> #include <QCoreApplication> +#include <QLoggingCategory> QT_BEGIN_NAMESPACE class QBuffer; @@ -39,6 +40,8 @@ QT_END_NAMESPACE namespace LanguageServerProtocol { +LANGUAGESERVERPROTOCOL_EXPORT Q_DECLARE_LOGGING_CATEGORY(parseLog) + class LANGUAGESERVERPROTOCOL_EXPORT BaseMessage { Q_DECLARE_TR_FUNCTIONS(BaseMessage) diff --git a/src/libs/languageserverprotocol/clientcapabilities.cpp b/src/libs/languageserverprotocol/clientcapabilities.cpp index 0200250444..f73c4ee04c 100644 --- a/src/libs/languageserverprotocol/clientcapabilities.cpp +++ b/src/libs/languageserverprotocol/clientcapabilities.cpp @@ -27,19 +27,6 @@ namespace LanguageServerProtocol { -SymbolCapabilities::SymbolKindCapabilities::SymbolKindCapabilities() -{ - setValueSet({SymbolKind::File, SymbolKind::Module, SymbolKind::Namespace, - SymbolKind::Package, SymbolKind::Class, SymbolKind::Method, - SymbolKind::Property, SymbolKind::Field, SymbolKind::Constructor, - SymbolKind::Enum, SymbolKind::Interface, SymbolKind::Function, - SymbolKind::Variable, SymbolKind::Constant, SymbolKind::String, - SymbolKind::Number, SymbolKind::Boolean, SymbolKind::Array, - SymbolKind::Object, SymbolKind::Key, SymbolKind::Null, - SymbolKind::EnumMember, SymbolKind::Struct, SymbolKind::Event, - SymbolKind::Operator, SymbolKind::TypeParameter}); -} - Utils::optional<QList<SymbolKind> > SymbolCapabilities::SymbolKindCapabilities::valueSet() const { Utils::optional<QList<int>> array = optionalArray<int>(valueSetKey); @@ -55,13 +42,6 @@ void SymbolCapabilities::SymbolKindCapabilities::setValueSet(const QList<SymbolK insert(valueSetKey, enumArrayToJsonArray<SymbolKind>(valueSet)); } - -ClientCapabilities::ClientCapabilities() -{ - setTextDocument(TextDocumentClientCapabilities()); - setWorkspace(WorkspaceClientCapabilities()); -} - bool ClientCapabilities::isValid(QStringList *error) const { return checkOptional<WorkspaceClientCapabilities>(error, workspaceKey) @@ -85,14 +65,6 @@ bool WorkspaceClientCapabilities::isValid(QStringList *error) const && checkOptional<bool>(error,configurationKey); } -TextDocumentClientCapabilities::SynchronizationCapabilities::SynchronizationCapabilities() -{ - setDynamicRegistration(true); - setWillSave(true); - setWillSaveWaitUntil(false); - setDidSave(true); -} - bool TextDocumentClientCapabilities::SynchronizationCapabilities::isValid(QStringList *error) const { return DynamicRegistrationCapabilities::isValid(error) @@ -101,19 +73,6 @@ bool TextDocumentClientCapabilities::SynchronizationCapabilities::isValid(QStrin && checkOptional<bool>(error, didSaveKey); } -TextDocumentClientCapabilities::TextDocumentClientCapabilities() -{ - setSynchronization(SynchronizationCapabilities()); - setDocumentSymbol(SymbolCapabilities()); - setCompletion(CompletionCapabilities()); - CodeActionCapabilities cac; - CodeActionCapabilities::CodeActionLiteralSupport literalSupport; - literalSupport.setCodeActionKind( - CodeActionCapabilities::CodeActionLiteralSupport::CodeActionKind(QList<QString>{"*"})); - cac.setCodeActionLiteralSupport(literalSupport); - setCodeAction(cac); -} - bool TextDocumentClientCapabilities::isValid(QStringList *error) const { return checkOptional<SynchronizationCapabilities>(error, synchronizationKey) @@ -136,24 +95,12 @@ bool TextDocumentClientCapabilities::isValid(QStringList *error) const && checkOptional<DynamicRegistrationCapabilities>(error, renameKey); } -SymbolCapabilities::SymbolCapabilities() -{ - setSymbolKind(SymbolKindCapabilities()); -} - bool SymbolCapabilities::isValid(QStringList *error) const { return DynamicRegistrationCapabilities::isValid(error) && checkOptional<SymbolKindCapabilities>(error, symbolKindKey); } -TextDocumentClientCapabilities::CompletionCapabilities::CompletionCapabilities() -{ - setDynamicRegistration(true); - setCompletionItem(CompletionItemCapbilities()); - setCompletionItemKind(CompletionItemKindCapabilities()); -} - bool TextDocumentClientCapabilities::CompletionCapabilities::isValid(QStringList *error) const { return DynamicRegistrationCapabilities::isValid(error) diff --git a/src/libs/languageserverprotocol/clientcapabilities.h b/src/libs/languageserverprotocol/clientcapabilities.h index c10341b3f0..3664007dd1 100644 --- a/src/libs/languageserverprotocol/clientcapabilities.h +++ b/src/libs/languageserverprotocol/clientcapabilities.h @@ -46,13 +46,11 @@ public: class LANGUAGESERVERPROTOCOL_EXPORT SymbolCapabilities : public DynamicRegistrationCapabilities { public: - SymbolCapabilities(); using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; - class SymbolKindCapabilities : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT SymbolKindCapabilities : public JsonObject { public: - SymbolKindCapabilities(); using JsonObject::JsonObject; /* @@ -85,13 +83,11 @@ public: class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentClientCapabilities : public JsonObject { public: - TextDocumentClientCapabilities(); using JsonObject::JsonObject; - class SynchronizationCapabilities : public DynamicRegistrationCapabilities + class LANGUAGESERVERPROTOCOL_EXPORT SynchronizationCapabilities : public DynamicRegistrationCapabilities { public: - SynchronizationCapabilities(); using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; // The client supports sending will save notifications. @@ -124,16 +120,14 @@ public: { insert(synchronizationKey, synchronization); } void clearSynchronization() { remove(synchronizationKey); } - class CompletionCapabilities : public DynamicRegistrationCapabilities + class LANGUAGESERVERPROTOCOL_EXPORT CompletionCapabilities : public DynamicRegistrationCapabilities { public: - CompletionCapabilities(); using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; - class CompletionItemCapbilities : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT CompletionItemCapbilities : public JsonObject { public: - CompletionItemCapbilities(); using JsonObject::JsonObject; /* @@ -180,7 +174,7 @@ public: { insert(completionItemKey, completionItem); } void clearCompletionItem() { remove(completionItemKey); } - class CompletionItemKindCapabilities : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT CompletionItemKindCapabilities : public JsonObject { public: CompletionItemKindCapabilities(); @@ -227,7 +221,7 @@ public: { insert(completionKey, completion); } void clearCompletion() { remove(completionKey); } - class HoverCapabilities : public DynamicRegistrationCapabilities + class LANGUAGESERVERPROTOCOL_EXPORT HoverCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; @@ -246,12 +240,12 @@ public: void setHover(const HoverCapabilities &hover) { insert(hoverKey, hover); } void clearHover() { remove(hoverKey); } - class SignatureHelpCapabilities : public DynamicRegistrationCapabilities + class LANGUAGESERVERPROTOCOL_EXPORT SignatureHelpCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; - class SignatureInformationCapabilities : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT SignatureInformationCapabilities : public JsonObject { public: using JsonObject::JsonObject; @@ -355,17 +349,17 @@ public: { insert(implementationKey, implementation); } void clearImplementation() { remove(implementationKey); } - class CodeActionCapabilities : public DynamicRegistrationCapabilities + class LANGUAGESERVERPROTOCOL_EXPORT CodeActionCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; - class CodeActionLiteralSupport : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT CodeActionLiteralSupport : public JsonObject { public: using JsonObject::JsonObject; - class CodeActionKind : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT CodeActionKind : public JsonObject { public: using JsonObject::JsonObject; @@ -454,7 +448,7 @@ public: void setApplyEdit(bool applyEdit) { insert(applyEditKey, applyEdit); } void clearApplyEdit() { remove(applyEditKey); } - class WorkspaceEditCapabilities : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceEditCapabilities : public JsonObject { public: using JsonObject::JsonObject; @@ -522,7 +516,6 @@ public: class LANGUAGESERVERPROTOCOL_EXPORT ClientCapabilities : public JsonObject { public: - ClientCapabilities(); using JsonObject::JsonObject; // Workspace specific client capabilities. diff --git a/src/libs/languageserverprotocol/icontent.h b/src/libs/languageserverprotocol/icontent.h index af14604739..1b57165b2e 100644 --- a/src/libs/languageserverprotocol/icontent.h +++ b/src/libs/languageserverprotocol/icontent.h @@ -92,7 +92,7 @@ using ResponseHandler = std::function<void(const QByteArray &, QTextCodec *)>; using ResponseHandlers = std::function<void(MessageId, const QByteArray &, QTextCodec *)>; using MethodHandler = std::function<void(const QString, MessageId, const IContent *)>; -inline LANGUAGESERVERPROTOCOL_EXPORT uint qHash(const LanguageServerProtocol::MessageId &id) +inline uint qHash(const LanguageServerProtocol::MessageId &id) { if (Utils::holds_alternative<int>(id)) return QT_PREPEND_NAMESPACE(qHash(Utils::get<int>(id))); @@ -102,8 +102,7 @@ inline LANGUAGESERVERPROTOCOL_EXPORT uint qHash(const LanguageServerProtocol::Me } template <typename Error> -inline LANGUAGESERVERPROTOCOL_EXPORT QDebug operator<<(QDebug stream, - const LanguageServerProtocol::MessageId &id) +inline QDebug operator<<(QDebug stream, const LanguageServerProtocol::MessageId &id) { if (Utils::holds_alternative<int>(id)) stream << Utils::get<int>(id); diff --git a/src/libs/languageserverprotocol/initializemessages.cpp b/src/libs/languageserverprotocol/initializemessages.cpp index 0464f8a13c..92e82d5107 100644 --- a/src/libs/languageserverprotocol/initializemessages.cpp +++ b/src/libs/languageserverprotocol/initializemessages.cpp @@ -54,27 +54,18 @@ QString Trace::toString() const } #undef RETURN_CASE -TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities::CompletionItemCapbilities() -{ -} - 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() @@ -111,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() diff --git a/src/libs/languageserverprotocol/jsonkeys.h b/src/libs/languageserverprotocol/jsonkeys.h index 6dfc40c252..e3673085eb 100644 --- a/src/libs/languageserverprotocol/jsonkeys.h +++ b/src/libs/languageserverprotocol/jsonkeys.h @@ -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"; diff --git a/src/libs/languageserverprotocol/jsonobject.cpp b/src/libs/languageserverprotocol/jsonobject.cpp index 1f471db47b..0156276a67 100644 --- a/src/libs/languageserverprotocol/jsonobject.cpp +++ b/src/libs/languageserverprotocol/jsonobject.cpp @@ -61,11 +61,7 @@ JsonObject &JsonObject::operator=(const JsonObject &other) = default; JsonObject &JsonObject::operator=(JsonObject &&other) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) m_jsonObject.swap(other.m_jsonObject); -#else - m_jsonObject = other.m_jsonObject; // NOTE use QJsonObject::swap when minimum required Qt version >= 5.10 -#endif return *this; } diff --git a/src/libs/languageserverprotocol/jsonrpcmessages.h b/src/libs/languageserverprotocol/jsonrpcmessages.h index 66c28bea4b..473c9fe580 100644 --- a/src/libs/languageserverprotocol/jsonrpcmessages.h +++ b/src/libs/languageserverprotocol/jsonrpcmessages.h @@ -232,6 +232,7 @@ template <typename Result, typename ErrorDataType> class Response : public JsonRpcMessage { public: + explicit Response(const MessageId &id) { setId(id); } using JsonRpcMessage::JsonRpcMessage; MessageId id() const diff --git a/src/libs/languageserverprotocol/languagefeatures.cpp b/src/libs/languageserverprotocol/languagefeatures.cpp index 06793217f1..cfb4cc6fab 100644 --- a/src/libs/languageserverprotocol/languagefeatures.cpp +++ b/src/libs/languageserverprotocol/languagefeatures.cpp @@ -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"); } @@ -334,31 +334,52 @@ 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 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; } diff --git a/src/libs/languageserverprotocol/languagefeatures.h b/src/libs/languageserverprotocol/languagefeatures.h index 30f3591e64..ddd732718a 100644 --- a/src/libs/languageserverprotocol/languagefeatures.h +++ b/src/libs/languageserverprotocol/languagefeatures.h @@ -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 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 @@ -332,9 +349,23 @@ public: using variant::variant; DocumentSymbolsResult() : variant(nullptr) {} DocumentSymbolsResult(const QJsonValue &value); + DocumentSymbolsResult(const DocumentSymbolsResult &other) : variant(other) {} + DocumentSymbolsResult(DocumentSymbolsResult &&other) : variant(std::move(other)) {} + using variant::operator=; + DocumentSymbolsResult &operator =(DocumentSymbolsResult &&other) + { + variant::operator=(std::move(other)); + return *this; + } + DocumentSymbolsResult &operator =(const DocumentSymbolsResult &other) + { + variant::operator=(other); + return *this; + } }; + class LANGUAGESERVERPROTOCOL_EXPORT DocumentSymbolsRequest : public Request<DocumentSymbolsResult, std::nullptr_t, DocumentSymbolParams> { diff --git a/src/libs/languageserverprotocol/lsptypes.cpp b/src/libs/languageserverprotocol/lsptypes.cpp index 991f7cc1f8..8aa1ecf81c 100644 --- a/src/libs/languageserverprotocol/lsptypes.cpp +++ b/src/libs/languageserverprotocol/lsptypes.cpp @@ -324,8 +324,10 @@ Position::Position(const QTextCursor &cursor) int Position::toPositionInDocument(QTextDocument *doc) const { const QTextBlock block = doc->findBlockByNumber(line()); - if (!block.isValid() || block.length() <= character()) + if (!block.isValid()) return -1; + if (block.length() <= character()) + return block.position() + block.length(); return block.position() + character(); } @@ -360,7 +362,7 @@ bool Range::overlaps(const Range &range) const return contains(range.start()) || contains(range.end()); } -bool DocumentFilter::applies(const Utils::FileName &fileName, const Utils::MimeType &mimeType) const +bool DocumentFilter::applies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType) const { if (Utils::optional<QString> _scheme = scheme()) { if (_scheme.value() == fileName.toString()) @@ -404,14 +406,30 @@ DocumentUri::DocumentUri(const QString &other) : QUrl(QUrl::fromPercentEncoding(other.toLocal8Bit())) { } -DocumentUri::DocumentUri(const Utils::FileName &other) +DocumentUri::DocumentUri(const Utils::FilePath &other) : QUrl(QUrl::fromLocalFile(other.toString())) { } -Utils::FileName DocumentUri::toFileName() const +Utils::FilePath DocumentUri::toFileName() const { - return isLocalFile() ? Utils::FileName::fromUserInput(QUrl(*this).toLocalFile()) - : Utils::FileName(); + return isLocalFile() ? Utils::FilePath::fromUserInput(QUrl(*this).toLocalFile()) + : Utils::FilePath(); +} + +MarkupKind::MarkupKind(const QJsonValue &value) +{ + m_value = value.toString() == "markdown" ? markdown : plaintext; +} + +LanguageServerProtocol::MarkupKind::operator QJsonValue() const +{ + switch (m_value) { + case MarkupKind::markdown: + return "markdown"; + case MarkupKind::plaintext: + return "plaintext"; + } + return {}; } } // namespace LanguageServerProtocol diff --git a/src/libs/languageserverprotocol/lsptypes.h b/src/libs/languageserverprotocol/lsptypes.h index 9fe9a47a63..ade3ac7ccf 100644 --- a/src/libs/languageserverprotocol/lsptypes.h +++ b/src/libs/languageserverprotocol/lsptypes.h @@ -45,16 +45,16 @@ class LANGUAGESERVERPROTOCOL_EXPORT DocumentUri : public QUrl { public: DocumentUri() = default; - Utils::FileName toFileName() const; + Utils::FilePath toFileName() const; static DocumentUri fromProtocol(const QString &uri) { return DocumentUri(uri); } - static DocumentUri fromFileName(const Utils::FileName &file) { return DocumentUri(file); } + static DocumentUri fromFileName(const Utils::FilePath &file) { return DocumentUri(file); } operator QJsonValue() const { return QJsonValue(toString()); } private: DocumentUri(const QString &other); - DocumentUri(const Utils::FileName &other); + DocumentUri(const Utils::FilePath &other); friend class LanguageClientValue<QString>; }; @@ -372,16 +372,30 @@ public: void setPattern(const QString &pattern) { insert(patternKey, pattern); } void clearPattern() { remove(patternKey); } - bool applies(const Utils::FileName &fileName, + bool applies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType = Utils::MimeType()) const; 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 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> diff --git a/src/libs/languageserverprotocol/lsputils.h b/src/libs/languageserverprotocol/lsputils.h index ee98db37f4..4646f181e9 100644 --- a/src/libs/languageserverprotocol/lsputils.h +++ b/src/libs/languageserverprotocol/lsputils.h @@ -71,6 +71,8 @@ public: using Utils::variant<QList<T>, std::nullptr_t>::variant; using Utils::variant<QList<T>, std::nullptr_t>::operator=; + LanguageClientArray() {} + LanguageClientArray(const QList<T> &list) { *this = list; } diff --git a/src/libs/languageserverprotocol/servercapabilities.cpp b/src/libs/languageserverprotocol/servercapabilities.cpp index fcd1fadeac..6ebf4f431f 100644 --- a/src/libs/languageserverprotocol/servercapabilities.cpp +++ b/src/libs/languageserverprotocol/servercapabilities.cpp @@ -161,7 +161,7 @@ bool ServerCapabilities::WorkspaceServerCapabilities::WorkspaceFoldersCapabiliti && checkOptional<QString, bool>(error, changeNotificationsKey); } -bool TextDocumentRegistrationOptions::filterApplies(const Utils::FileName &fileName, +bool TextDocumentRegistrationOptions::filterApplies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType) const { const LanguageClientArray<DocumentFilter> &selector = documentSelector(); diff --git a/src/libs/languageserverprotocol/servercapabilities.h b/src/libs/languageserverprotocol/servercapabilities.h index 0e31821b17..71d3e4a496 100644 --- a/src/libs/languageserverprotocol/servercapabilities.h +++ b/src/libs/languageserverprotocol/servercapabilities.h @@ -52,7 +52,7 @@ public: void setDocumentSelector(const LanguageClientArray<DocumentFilter> &documentSelector) { insert(documentSelectorKey, documentSelector.toJson()); } - bool filterApplies(const Utils::FileName &fileName, + bool filterApplies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType = Utils::MimeType()) const; bool isValid(QStringList *error) const override @@ -268,7 +268,7 @@ public: void setDocumentSelector(const LanguageClientArray<DocumentFilter> &documentSelector) { insert(documentSelectorKey, documentSelector.toJson()); } - bool filterApplies(const Utils::FileName &fileName, + bool filterApplies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType = Utils::MimeType()) const; // The id used to register the request. The id can be used to deregister diff --git a/src/libs/languageserverprotocol/textsynchronization.h b/src/libs/languageserverprotocol/textsynchronization.h index 2b659366cd..fa81cae51a 100644 --- a/src/libs/languageserverprotocol/textsynchronization.h +++ b/src/libs/languageserverprotocol/textsynchronization.h @@ -83,7 +83,7 @@ public: void setTextDocument(const VersionedTextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } - class TextDocumentContentChangeEvent : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentContentChangeEvent : public JsonObject { /* * An event describing a change to a text document. If range and rangeLength are omitted diff --git a/src/libs/languageserverprotocol/workspace.cpp b/src/libs/languageserverprotocol/workspace.cpp index 9f73af2ac0..e411878877 100644 --- a/src/libs/languageserverprotocol/workspace.cpp +++ b/src/libs/languageserverprotocol/workspace.cpp @@ -98,4 +98,14 @@ ExecuteCommandParams::ExecuteCommandParams(const Command &command) setArguments(command.arguments().value()); } +LanguageServerProtocol::WorkSpaceFolderResult::operator const QJsonValue() const +{ + if (!Utils::holds_alternative<QList<WorkSpaceFolder>>(*this)) + return QJsonValue::Null; + QJsonArray array; + for (auto folder : Utils::get<QList<WorkSpaceFolder>>(*this)) + array.append(QJsonValue(folder)); + return array; +} + } // namespace LanguageServerProtocol diff --git a/src/libs/languageserverprotocol/workspace.h b/src/libs/languageserverprotocol/workspace.h index 5f69d2c782..bf6a1b9096 100644 --- a/src/libs/languageserverprotocol/workspace.h +++ b/src/libs/languageserverprotocol/workspace.h @@ -29,8 +29,17 @@ namespace LanguageServerProtocol { +class LANGUAGESERVERPROTOCOL_EXPORT WorkSpaceFolderResult + : public Utils::variant<QList<WorkSpaceFolder>, std::nullptr_t> +{ +public: + using variant::variant; + using variant::operator=; + operator const QJsonValue() const; +}; + class LANGUAGESERVERPROTOCOL_EXPORT WorkSpaceFolderRequest : public Request< - Utils::variant<QList<WorkSpaceFolder>, Utils::nullopt_t>, std::nullptr_t, std::nullptr_t> + WorkSpaceFolderResult, std::nullptr_t, std::nullptr_t> { public: WorkSpaceFolderRequest(); |