// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "languagefeatures.h" #include namespace LanguageServerProtocol { constexpr const char HoverRequest::methodName[]; constexpr const char GotoDefinitionRequest::methodName[]; constexpr const char GotoTypeDefinitionRequest::methodName[]; constexpr const char GotoImplementationRequest::methodName[]; constexpr const char FindReferencesRequest::methodName[]; constexpr const char DocumentHighlightsRequest::methodName[]; constexpr const char DocumentSymbolsRequest::methodName[]; constexpr const char CodeActionRequest::methodName[]; constexpr const char CodeLensRequest::methodName[]; constexpr const char CodeLensResolveRequest::methodName[]; constexpr const char DocumentLinkRequest::methodName[]; constexpr const char DocumentLinkResolveRequest::methodName[]; constexpr const char DocumentColorRequest::methodName[]; constexpr const char ColorPresentationRequest::methodName[]; constexpr const char DocumentFormattingRequest::methodName[]; constexpr const char DocumentRangeFormattingRequest::methodName[]; constexpr const char DocumentOnTypeFormattingRequest::methodName[]; constexpr const char RenameRequest::methodName[]; constexpr const char SignatureHelpRequest::methodName[]; constexpr const char PrepareRenameRequest::methodName[]; HoverContent LanguageServerProtocol::Hover::content() const { return HoverContent(value(contentsKey)); } void Hover::setContent(const HoverContent &content) { if (auto val = std::get_if(&content)) insert(contentsKey, *val); else if (auto val = std::get_if(&content)) insert(contentsKey, *val); else if (auto val = std::get_if>(&content)) insert(contentsKey, LanguageClientArray(*val).toJson()); else QTC_ASSERT_STRING("LanguageClient Using unknown type Hover::setContent"); } HoverRequest::HoverRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } std::optional ParameterInformation::documentation() const { QJsonValue documentation = value(documentationKey); if (documentation.isUndefined()) return std::nullopt; return MarkupOrString(documentation); } GotoDefinitionRequest::GotoDefinitionRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } GotoTypeDefinitionRequest::GotoTypeDefinitionRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } GotoImplementationRequest::GotoImplementationRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } FindReferencesRequest::FindReferencesRequest(const ReferenceParams ¶ms) : Request(methodName, params) { } DocumentHighlightsRequest::DocumentHighlightsRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } DocumentSymbolsRequest::DocumentSymbolsRequest(const DocumentSymbolParams ¶ms) : Request(methodName, params) { } std::optional > CodeActionParams::CodeActionContext::only() const { return optionalArray(onlyKey); } void CodeActionParams::CodeActionContext::setOnly(const QList &only) { insertArray(onlyKey, only); } CodeActionRequest::CodeActionRequest(const CodeActionParams ¶ms) : Request(methodName, params) { } CodeLensRequest::CodeLensRequest(const CodeLensParams ¶ms) : Request(methodName, params) { } CodeLensResolveRequest::CodeLensResolveRequest(const CodeLens ¶ms) : Request(methodName, params) { } DocumentLinkRequest::DocumentLinkRequest(const DocumentLinkParams ¶ms) : Request(methodName, params) { } DocumentLinkResolveRequest::DocumentLinkResolveRequest(const DocumentLink ¶ms) : Request(methodName, params) { } DocumentColorRequest::DocumentColorRequest(const DocumentColorParams ¶ms) : Request(methodName, params) { } ColorPresentationRequest::ColorPresentationRequest(const ColorPresentationParams ¶ms) : Request(methodName, params) { } QHash FormattingOptions::properties() const { QHash ret; for (const QString &key : keys()) { if (key == tabSizeKey || key == insertSpaceKey) continue; QJsonValue property = value(key); if (property.isBool()) ret[key] = property.toBool(); if (property.isDouble()) ret[key] = property.toDouble(); if (property.isString()) ret[key] = property.toString(); } return ret; } void FormattingOptions::setProperty(const Key key, const DocumentFormattingProperty &property) { using namespace std; if (auto val = get_if(&property)) insert(key, *val); else if (auto val = get_if(&property)) insert(key, *val); else if (auto val = get_if(&property)) insert(key, *val); } DocumentFormattingRequest::DocumentFormattingRequest(const DocumentFormattingParams ¶ms) : Request(methodName, params) { } DocumentRangeFormattingRequest::DocumentRangeFormattingRequest( const DocumentRangeFormattingParams ¶ms) : Request(methodName, params) { } bool DocumentOnTypeFormattingParams::isValid() const { return contains(textDocumentKey) && contains(positionKey) && contains(chKey) && contains(optionsKey); } DocumentOnTypeFormattingRequest::DocumentOnTypeFormattingRequest( const DocumentOnTypeFormattingParams ¶ms) : Request(methodName, params) { } PrepareRenameRequest::PrepareRenameRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } bool RenameParams::isValid() const { return contains(textDocumentKey) && contains(positionKey) && contains(newNameKey); } RenameRequest::RenameRequest(const RenameParams ¶ms) : Request(methodName, params) { } std::optional DocumentLink::target() const { if (std::optional optionalTarget = optionalValue(targetKey)) return std::make_optional(DocumentUri::fromProtocol(*optionalTarget)); return std::nullopt; } std::optional DocumentLink::data() const { return contains(dataKey) ? std::make_optional(value(dataKey)) : std::nullopt; } TextDocumentParams::TextDocumentParams() : TextDocumentParams(TextDocumentIdentifier()) { } TextDocumentParams::TextDocumentParams(const TextDocumentIdentifier &identifier) : JsonObject() { setTextDocument(identifier); } GotoResult::GotoResult(const QJsonValue &value) { if (value.isArray()) { QList locations; for (auto arrayValue : value.toArray()) { if (arrayValue.isObject()) locations.append(Location(arrayValue.toObject())); } emplace>(locations); } else if (value.isObject()) { emplace(value.toObject()); } else { emplace(nullptr); } } template QList documentSymbolsResultArray(const QJsonArray &array) { QList ret; for (const auto &arrayValue : array) { if (arrayValue.isObject()) ret << Symbol(arrayValue.toObject()); } return ret; } DocumentSymbolsResult::DocumentSymbolsResult(const QJsonValue &value) { if (value.isArray()) { QJsonArray array = value.toArray(); if (array.isEmpty()) { *this = QList(); } else { QJsonObject arrayObject = array.first().toObject(); if (arrayObject.contains(rangeKey)) *this = documentSymbolsResultArray(array); else *this = documentSymbolsResultArray(array); } } else { *this = nullptr; } } DocumentHighlightsResult::DocumentHighlightsResult(const QJsonValue &value) { if (value.isArray()) { QList highlights; for (auto arrayValue : value.toArray()) { if (arrayValue.isObject()) highlights.append(DocumentHighlight(arrayValue.toObject())); } *this = highlights; } else { *this = nullptr; } } template<> MarkedString fromJsonValue(const QJsonValue &value) { return MarkedString(value); } MarkedString::MarkedString(const QJsonValue &value) { if (value.isObject()) emplace(MarkedLanguageString(value.toObject())); else emplace(value.toString()); } bool MarkedString::isValid() const { if (auto markedLanguageString = std::get_if(this)) return markedLanguageString->isValid(); return true; } LanguageServerProtocol::MarkedString::operator QJsonValue() const { if (auto val = std::get_if(this)) return *val; if (auto val = std::get_if(this)) return QJsonValue(*val); return {}; } HoverContent::HoverContent(const QJsonValue &value) { if (value.isArray()) { emplace>(LanguageClientArray(value).toList()); } else if (value.isObject()) { const QJsonObject &object = value.toObject(); MarkedLanguageString markedLanguageString(object); if (markedLanguageString.isValid()) emplace(markedLanguageString); else emplace(MarkupContent(object)); } else if (value.isString()) { emplace(MarkedString(value.toString())); } } bool HoverContent::isValid() const { if (const auto s = std::get_if(this)) return s->isValid(); return true; } DocumentFormattingProperty::DocumentFormattingProperty(const QJsonValue &value) { if (value.isBool()) *this = value.toBool(); if (value.isDouble()) *this = value.toDouble(); if (value.isString()) *this = value.toString(); } SignatureHelpRequest::SignatureHelpRequest(const TextDocumentPositionParams ¶ms) : Request(methodName, params) { } CodeActionResult::CodeActionResult(const QJsonValue &val) { using ResultArray = QList>; if (val.isArray()) { const QJsonArray array = val.toArray(); ResultArray result; for (const QJsonValue &val : array) { if (val.toObject().value(commandKey).isString()) { const Command command(val); if (command.isValid()) result << command; } else { const CodeAction action(val); if (action.isValid()) result << action; } } emplace(result); return; } emplace(nullptr); } PrepareRenameResult::PrepareRenameResult() : std::variant(nullptr) {} PrepareRenameResult::PrepareRenameResult( const std::variant &val) : std::variant(val) {} PrepareRenameResult::PrepareRenameResult(const PlaceHolderResult &val) : std::variant(val) {} PrepareRenameResult::PrepareRenameResult(const Range &val) : std::variant(val) {} PrepareRenameResult::PrepareRenameResult(const QJsonValue &val) { if (val.isNull()) { emplace(nullptr); } else if (val.isObject()) { const QJsonObject object = val.toObject(); if (object.keys().contains(rangeKey)) emplace(PlaceHolderResult(object)); else emplace(Range(object)); } } std::optional CodeLens::data() const { return contains(dataKey) ? std::make_optional(value(dataKey)) : std::nullopt; } HoverResult::HoverResult(const QJsonValue &value) { if (value.isObject()) emplace(Hover(value.toObject())); else emplace(nullptr); } bool HoverResult::isValid() const { if (auto hover = std::get_if(this)) return hover->isValid(); return true; } } // namespace LanguageServerProtocol