From 0a775d9b3209be15dea8b8915fc0a1c8e0046ba6 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 16 Jan 2021 18:19:45 +0100 Subject: Updated copyright statements upon Git audit After going through all the files and the history of commits on them it was clear that some copyright statements are obsolete (the code has been overwritten since) and some are missing. This commit tries best to remedy that, along with adding SPDX tags where they were still not used. Also, a minimal SPDX convention is documented for further contributions. Closes #426. --- gtad/data.h.mustache | 4 ++++ gtad/operation.cpp.mustache | 4 ++++ gtad/operation.h.mustache | 4 ++++ 3 files changed, 12 insertions(+) (limited to 'gtad') diff --git a/gtad/data.h.mustache b/gtad/data.h.mustache index 32ea85ee..a2193380 100644 --- a/gtad/data.h.mustache +++ b/gtad/data.h.mustache @@ -1,3 +1,7 @@ +{{! +SPDX-FileCopyrightText: 2020 Kitsune Ral +SPDX-License-Identifier: LGPL-2.1-or-later +}} {{>preamble}} #pragma once diff --git a/gtad/operation.cpp.mustache b/gtad/operation.cpp.mustache index 3c3396e9..1d0ae476 100644 --- a/gtad/operation.cpp.mustache +++ b/gtad/operation.cpp.mustache @@ -1,3 +1,7 @@ +{{! +SPDX-FileCopyrightText: 2020 Kitsune Ral +SPDX-License-Identifier: LGPL-2.1-or-later +}} {{>preamble}} #include "{{filenameBase}}.h" diff --git a/gtad/operation.h.mustache b/gtad/operation.h.mustache index 36963b9a..135eee55 100644 --- a/gtad/operation.h.mustache +++ b/gtad/operation.h.mustache @@ -1,3 +1,7 @@ +{{! +SPDX-FileCopyrightText: 2020 Kitsune Ral +SPDX-License-Identifier: LGPL-2.1-or-later +}} {{>preamble}} #pragma once -- cgit v1.2.3 From fefa95b86c31f3b7e46fc28327b23050cbadedb9 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Wed, 23 Jun 2021 13:41:44 +0200 Subject: Update to the new matrix-doc layout and tooling Among things affecting Quotient, the update involved moving API files from api/ to data/api/, adding extensions to event schema files, and switching from ReStructured Text to Markdown as a lightweight markup language. This commit updates the build system and GTAD configuration to accommodate for these. The build system is also more robust now in choosing whether the update-api target should be provided. Previously the target was provided whenever GTAD_PATH and MATRIX_DOC_PATH were specified, even if they did not point to anything valid. CMake now checks that MATRIX_DOC_PATH is an actual directory and that GTAD_PATH points to an actual file. # Conflicts: # CMakeLists.txt --- CMakeLists.txt | 26 ++++++++++++++++++-------- gtad/gtad.yaml | 4 ++-- 2 files changed, 20 insertions(+), 10 deletions(-) (limited to 'gtad') diff --git a/CMakeLists.txt b/CMakeLists.txt index d930bbf2..555ffa96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -174,16 +174,26 @@ set(FULL_CSAPI_DIR lib/${CSAPI_DIR}) set(ASAPI_DEF_DIR application-service/definitions) set(ISAPI_DEF_DIR identity/definitions) -if (GTAD_PATH) +if (GTAD_PATH AND MATRIX_DOC_PATH) get_filename_component(ABS_GTAD_PATH "${GTAD_PATH}" REALPATH) + if (EXISTS ${ABS_GTAD_PATH}) + get_filename_component(ABS_API_DEF_PATH "${MATRIX_DOC_PATH}/data/api" REALPATH) + if (NOT IS_DIRECTORY ${ABS_API_DEF_PATH}) + # Check the old place of API files + get_filename_component(ABS_API_DEF_PATH "${MATRIX_DOC_PATH}/api" REALPATH) + endif () + if (IS_DIRECTORY ${ABS_API_DEF_PATH}) + set(API_GENERATION_ENABLED 1) + else () + message( WARNING "${MATRIX_DOC_PATH} doesn't seem to point to a valid matrix-doc repo; disabling API stubs generation") + endif () + else (EXISTS ${ABS_GTAD_PATH}) + message( WARNING "${GTAD_PATH} doesn't exist; disabling API stubs generation") + endif () endif () -if (MATRIX_DOC_PATH) - get_filename_component(ABS_API_DEF_PATH "${MATRIX_DOC_PATH}/api" REALPATH) -endif () -if (ABS_GTAD_PATH AND ABS_API_DEF_PATH) +if (API_GENERATION_ENABLED) message( STATUS "Using GTAD at ${ABS_GTAD_PATH}" ) - message( STATUS "Using API files at ${ABS_API_DEF_PATH}" ) - set(API_GENERATION_ENABLED 1) + message( STATUS "Found API files at ${ABS_API_DEF_PATH}" ) if (NOT CLANG_FORMAT) set(CLANG_FORMAT clang-format) endif() @@ -225,7 +235,7 @@ if (ABS_GTAD_PATH AND ABS_API_DEF_PATH) VERBATIM ) add_custom_target(update-api DEPENDS generate-unformatted-api) - if (ABS_CLANG_FORMAT) + if (EXISTS ${ABS_CLANG_FORMAT}) set(CLANG_FORMAT_ARGS -i -sort-includes ${CLANG_FORMAT_ARGS}) # FIXME: the list of files should be produced after GTAD has run. # For now it's produced at CMake invocation. If file() hasn't found diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index adf5024a..d68cc8a0 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -85,7 +85,7 @@ analyzer: { type: RoomEventPtr, imports: "events/eventloader.h" } - /event.yaml$/: { type: EventPtr, imports: "events/eventloader.h" } - - /m\.room\.member$/: void # Skip resolving; see EventsArray<> below + - /m\.room\.member/: void # Skip resolving; see EventsArray<> below - '/^(\./)?definitions/request_email_validation.yaml$/': title: EmailValidationData - '/^(\./)?definitions/request_msisdn_validation.yaml$/': @@ -109,7 +109,7 @@ analyzer: - /^Notification|Result$/: type: "std::vector<{{1}}>" imports: "events/eventloader.h" - - /m\.room\.member$/: # Only used in an array (see also above) + - /m\.room\.member/: # Only used in an array (see also above) type: "EventsArray" imports: "events/roommemberevent.h" - /state_event.yaml$/: StateEvents -- cgit v1.2.3 From 65e6ecd9711372e1e2afde769967ee46b3920307 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Wed, 23 Jun 2021 19:12:26 +0200 Subject: *.mustache: Drop a stray leading end-of-line An SPDX comment in the source code did not collapse entirely. --- gtad/data.h.mustache | 3 +-- gtad/operation.cpp.mustache | 3 +-- gtad/operation.h.mustache | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'gtad') diff --git a/gtad/data.h.mustache b/gtad/data.h.mustache index a2193380..1b511262 100644 --- a/gtad/data.h.mustache +++ b/gtad/data.h.mustache @@ -1,8 +1,7 @@ {{! SPDX-FileCopyrightText: 2020 Kitsune Ral SPDX-License-Identifier: LGPL-2.1-or-later -}} -{{>preamble}} +}}{{>preamble}} #pragma once #include "converters.h" diff --git a/gtad/operation.cpp.mustache b/gtad/operation.cpp.mustache index 1d0ae476..5bbc45ec 100644 --- a/gtad/operation.cpp.mustache +++ b/gtad/operation.cpp.mustache @@ -1,8 +1,7 @@ {{! SPDX-FileCopyrightText: 2020 Kitsune Ral SPDX-License-Identifier: LGPL-2.1-or-later -}} -{{>preamble}} +}}{{>preamble}} #include "{{filenameBase}}.h" #include diff --git a/gtad/operation.h.mustache b/gtad/operation.h.mustache index 135eee55..f91dc66c 100644 --- a/gtad/operation.h.mustache +++ b/gtad/operation.h.mustache @@ -1,8 +1,7 @@ {{! SPDX-FileCopyrightText: 2020 Kitsune Ral SPDX-License-Identifier: LGPL-2.1-or-later -}} -{{>preamble}} +}}{{>preamble}} #pragma once #include "jobs/basejob.h" -- cgit v1.2.3 From ac8a4487e0254386462c43bfc0aeef8412854117 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 28 Jun 2021 20:32:14 +0200 Subject: gtad.yaml: update for use with GTAD pre-0.8 --- gtad/gtad.yaml | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'gtad') diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index d68cc8a0..e56c394d 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -77,28 +77,31 @@ analyzer: +on: - object: &QJsonObject { type: QJsonObject } - $ref: - - +set: { moveOnly: } + - +set: + moveOnly: + imports: '"events/eventloader.h"' +on: - - /state_event.yaml$/: - { type: StateEventPtr, imports: "events/eventloader.h" } - - /room_event.yaml$/: - { type: RoomEventPtr, imports: "events/eventloader.h" } - - /event.yaml$/: - { type: EventPtr, imports: "events/eventloader.h" } + - /state_event.yaml$/: StateEventPtr + - /room_event.yaml$/: RoomEventPtr + - /event.yaml$/: EventPtr - /m\.room\.member/: void # Skip resolving; see EventsArray<> below - - '/^(\./)?definitions/request_email_validation.yaml$/': - title: EmailValidationData - - '/^(\./)?definitions/request_msisdn_validation.yaml$/': - title: MsisdnValidationData - - /_filter.yaml$/: # Event/RoomEventFilters do NOT need Omittable<> - - /public_rooms_response.yaml$/: { _inline: true } - - //: *UseOmittable # Also apply "avoidCopy" to all other ref'ed types + - +set: + # This renderer actually applies to all $ref things + _importRenderer: '"{{#segments}}{{_}}{{#_join}}/{{/_join}}{{/segments}}.h"' + +on: + - '/^(\./)?definitions/request_email_validation.yaml$/': + title: EmailValidationData + - '/^(\./)?definitions/request_msisdn_validation.yaml$/': + title: MsisdnValidationData + - /_filter.yaml$/: # Event/RoomEventFilters do NOT need Omittable<> + - /public_rooms_response.yaml$/: { _inline: true } + - //: *UseOmittable # Also apply "avoidCopy" to all other ref'ed types - schema: - getTurnServer<: *QJsonObject # It's used as an opaque JSON object - PublicRoomResponse: { _inline: true } # - defineFilter>: &Filter # Force folding into a structure # type: Filter -# imports: "csapi/definitions/sync_filter.h" +# imports: '"csapi/definitions/sync_filter.h"' # - getFilter<: *Filter - RoomFilter: # A structure inside Filter, same story as with *_filter.yaml - //: *UseOmittable @@ -108,10 +111,10 @@ analyzer: +on: - /^Notification|Result$/: type: "std::vector<{{1}}>" - imports: "events/eventloader.h" + imports: '"events/eventloader.h"' - /m\.room\.member/: # Only used in an array (see also above) type: "EventsArray" - imports: "events/roommemberevent.h" + imports: '"events/roommemberevent.h"' - /state_event.yaml$/: StateEvents - /room_event.yaml$/: RoomEvents - /event.yaml$/: Events @@ -134,7 +137,6 @@ mustache: # _quote: '"' # Common quote for left and right # _leftQuote: '"' # _rightQuote: '"' -# _joinChar: ',' # The character used by {{_join}} - not working yet _comment: '//' copyrightName: Kitsune Ral copyrightEmail: -- cgit v1.2.3 From 7f4ef8b303c36831a9172a1fc60888e906fc9b93 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Wed, 30 Jun 2021 20:10:40 +0200 Subject: Add a commented out delimiter override example --- gtad/gtad.yaml | 1 + 1 file changed, 1 insertion(+) (limited to 'gtad') diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index e56c394d..928a1495 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -132,6 +132,7 @@ analyzer: #operations: mustache: +# delimiter: '%| |%' # or something else instead of '{{ }}' constants: # Syntax elements used by GTAD # _quote: '"' # Common quote for left and right -- cgit v1.2.3 From b64bfa8f72084d9d9397001a735e985a4bf94e56 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Fri, 2 Jul 2021 10:33:59 +0200 Subject: Abandon BaseJob::Query - Mustache template --- gtad/operation.cpp.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gtad') diff --git a/gtad/operation.cpp.mustache b/gtad/operation.cpp.mustache index 5bbc45ec..f34c9280 100644 --- a/gtad/operation.cpp.mustache +++ b/gtad/operation.cpp.mustache @@ -13,7 +13,7 @@ using namespace Quotient; auto queryTo{{camelCaseOperationId}}( {{#queryParams}}{{>joinedParamDef}}{{/queryParams}}) { - BaseJob::Query _q;{{#queryParams}} + QUrlQuery _q;{{#queryParams}} addParam<{{^required?}}IfNotEmpty{{/required?}}>(_q, QStringLiteral("{{baseName}}"), {{paramName}});{{/queryParams}} return _q; -- cgit v1.2.3 From 08d5cef8bbbef65c961370d4a9e2c48a6d7281f1 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 7 Aug 2021 22:08:11 +0200 Subject: gtad.yaml: use QUrl where API uses 'format: uri' --- gtad/gtad.yaml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'gtad') diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index 928a1495..58e1909c 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -68,6 +68,9 @@ analyzer: - dateTime: type: QDateTime initializer: QDateTime::fromString("{{defaultValue}}") + - uri: + type: QUrl + initializer: QUrl::fromEncoded("{{defaultValue}}") - //: &QString type: QString initializer: QStringLiteral("{{defaultValue}}") -- cgit v1.2.3 From 71384a49c3a053e715241172d9d9893bb1742e6b Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 22 Aug 2021 19:37:09 +0200 Subject: Mustache: avoid BaseJob::Data It's about to be deprecated in the next commits. --- gtad/operation.cpp.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gtad') diff --git a/gtad/operation.cpp.mustache b/gtad/operation.cpp.mustache index f34c9280..7f692e4a 100644 --- a/gtad/operation.cpp.mustache +++ b/gtad/operation.cpp.mustache @@ -36,7 +36,7 @@ QUrl {{camelCaseOperationId}}Job::makeRequestUrl(QUrl baseUrl{{#allParams?}}, { {{#headerParams}} setRequestHeader("{{baseName}}", {{paramName}}.toLatin1()); {{/headerParams}}{{#inlineBody}}{{^propertyMap}}{{^bodyParams?}} - setRequestData(Data({{#consumesNonJson?}}{{nameCamelCase}}{{/consumesNonJson? + setRequestData(RequestData({{#consumesNonJson?}}{{nameCamelCase}}{{/consumesNonJson? }}{{^consumesNonJson?}}toJson({{nameCamelCase}}){{/consumesNonJson?}})); {{/bodyParams?}}{{/propertyMap}}{{/inlineBody }}{{^consumesNonJson?}}{{#bodyParams?}} -- cgit v1.2.3 From 7c11f7fddbcc98e4b3b92060c475799d7518624c Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 18:26:47 +0200 Subject: gtad.yaml: make _rightQuote example less trivial --- gtad/gtad.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gtad') diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index 58e1909c..ee8a43fe 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -140,7 +140,7 @@ mustache: # Syntax elements used by GTAD # _quote: '"' # Common quote for left and right # _leftQuote: '"' -# _rightQuote: '"' +# _rightQuote: '"_ls' _comment: '//' copyrightName: Kitsune Ral copyrightEmail: -- cgit v1.2.3 From 96f31d7d8ed1c9ab905c24ac039079aea622f4dc Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 18:39:21 +0200 Subject: BaseJob: percent-encode variable path parts This is meant to spare clients from having to percent-encode room aliases, v3 event ids etc. that happen to hit the endpoint path. It is unfair to expect clients to do that since they are not supposed to care about the shape of CS API, which parameter should be encoded in which way. The trick (together with the slightly updated GTAD configuration) is to percent-encode parts that happen to be QStrings and not `const char[]`'s while passing all constant parts as plain C character literals. This also allows to make it more certain that the path is correctly encoded by passing and storing QByteArray's wherever the path is already encoded, and only use QStrings (next to const char arrays) before that. Since the change alters the API contract (even if that contract was crappy), some crude detection of percent-encoded stuff on input is inserted; if input is already percent-encoded, a warning is put to the logs, alerting developers about the change. --- gtad/gtad.yaml | 4 ++-- gtad/operation.cpp.mustache | 2 -- lib/jobs/basejob.cpp | 51 +++++++++++++++++++++++++++++++-------------- lib/jobs/basejob.h | 21 ++++++++++++++++--- lib/jobs/syncjob.cpp | 2 +- 5 files changed, 56 insertions(+), 24 deletions(-) (limited to 'gtad') diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index ee8a43fe..943ac013 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -190,8 +190,8 @@ mustache: joinedParamDef: "{{>maybeCrefType}} {{paramName}}{{>cjoin}}" passPathAndMaybeQuery: >- - QStringLiteral("{{basePathWithoutHost}}") - {{#pathParts}} % {{_}}{{/pathParts}}{{#queryParams?}}, + makePath("{{basePathWithoutHost}}"{{#pathParts}}, + {{_}}{{/pathParts}}){{#queryParams?}}, queryTo{{camelCaseOperationId}}( {{#queryParams}}{{paramName}}{{>cjoin}}{{/queryParams}}){{/queryParams?}} diff --git a/gtad/operation.cpp.mustache b/gtad/operation.cpp.mustache index 7f692e4a..3d26ec73 100644 --- a/gtad/operation.cpp.mustache +++ b/gtad/operation.cpp.mustache @@ -4,8 +4,6 @@ SPDX-License-Identifier: LGPL-2.1-or-later }}{{>preamble}} #include "{{filenameBase}}.h" -#include - using namespace Quotient; {{#operations}}{{#operation}} {{#queryParams?}} diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 85066024..73762e4f 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -71,7 +71,7 @@ public: // Using an idiom from clang-tidy: // http://clang.llvm.org/extra/clang-tidy/checks/modernize-pass-by-value.html - Private(HttpVerb v, QString endpoint, const QUrlQuery& q, + Private(HttpVerb v, QByteArray endpoint, const QUrlQuery& q, RequestData&& data, bool nt) : verb(v) , apiEndpoint(std::move(endpoint)) @@ -106,7 +106,7 @@ public: // Contents for the network request HttpVerb verb; - QString apiEndpoint; + QByteArray apiEndpoint; QHash requestHeaders; QUrlQuery requestQuery; RequestData requestData; @@ -166,14 +166,36 @@ public: } }; -BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, +inline bool isHex(QChar c) +{ + return c.isDigit() || (c >= u'A' && c <= u'F') || (c >= u'a' && c <= u'f'); +} + +QByteArray BaseJob::encodeIfParam(const QString& paramPart) +{ + const auto percentIndex = paramPart.indexOf('%'); + if (percentIndex != -1 && paramPart.size() > percentIndex + 2 + && isHex(paramPart[percentIndex + 1]) + && isHex(paramPart[percentIndex + 2])) { + qCWarning(JOBS) + << "Developers, upfront percent-encoding of job parameters is " + "deprecated since libQuotient 0.7; the string involved is" + << paramPart; + return QUrl(paramPart, QUrl::TolerantMode).toEncoded(); + } + return QUrl::toPercentEncoding(paramPart); +} + +BaseJob::BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint, bool needsToken) - : BaseJob(verb, name, endpoint, QUrlQuery {}, RequestData {}, needsToken) + : BaseJob(verb, name, std::move(endpoint), QUrlQuery {}, RequestData {}, + needsToken) {} -BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, +BaseJob::BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint, const QUrlQuery& query, RequestData&& data, bool needsToken) - : d(new Private(verb, endpoint, query, std::move(data), needsToken)) + : d(new Private(verb, std::move(endpoint), query, std::move(data), + needsToken)) { setObjectName(name); connect(&d->timer, &QTimer::timeout, this, &BaseJob::timeout); @@ -194,13 +216,6 @@ QUrl BaseJob::requestUrl() const { return d->reply ? d->reply->url() : QUrl(); } bool BaseJob::isBackground() const { return d->inBackground; } -//const QString& BaseJob::apiEndpoint() const { return d->apiUrl.path(); } - -//void BaseJob::setApiEndpoint(const QString& apiEndpoint) -//{ -// d->apiEndpoint = apiEndpoint; -//} - const BaseJob::headers_t& BaseJob::requestHeaders() const { return d->requestHeaders; @@ -259,13 +274,17 @@ const QNetworkReply* BaseJob::reply() const { return d->reply.data(); } QNetworkReply* BaseJob::reply() { return d->reply.data(); } -QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QString& path, +QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QByteArray& encodedPath, const QUrlQuery& query) { // Make sure the added path is relative even if it's not (the official // API definitions have the leading slash though it's not really correct). - baseUrl = baseUrl.resolved( - QUrl(path.mid(path.startsWith('/')), QUrl::TolerantMode)); + const auto pathUrl = + QUrl::fromEncoded(encodedPath.mid(encodedPath.startsWith('/')), + QUrl::StrictMode); + Q_ASSERT_X(pathUrl.isValid(), __FUNCTION__, + qPrintable(pathUrl.errorString())); + baseUrl = baseUrl.resolved(pathUrl); baseUrl.setQuery(query); return baseUrl; } diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 663c121c..81455307 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -9,6 +9,7 @@ #include "../converters.h" #include +#include class QNetworkReply; class QSslError; @@ -23,6 +24,14 @@ class BaseJob : public QObject { Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT) Q_PROPERTY(int maxRetries READ maxRetries WRITE setMaxRetries) Q_PROPERTY(int statusCode READ error NOTIFY statusChanged) + + static QByteArray encodeIfParam(const QString& paramPart); + template + static inline auto encodeIfParam(const char (&constPart)[N]) + { + return constPart; + } + public: /*! The status code of a job * @@ -70,6 +79,12 @@ public: }; Q_ENUM(StatusCode) + template + static QByteArray makePath(StrTs&&... parts) + { + return (QByteArray() % ... % encodeIfParam(parts)); + } + using Data #ifndef Q_CC_MSVC Q_DECL_DEPRECATED_X("Use Quotient::RequestData instead") @@ -124,9 +139,9 @@ public: }; public: - BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, + BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint, bool needsToken = true); - BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, + BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint, const QUrlQuery& query, RequestData&& data = {}, bool needsToken = true); @@ -352,7 +367,7 @@ protected: * The function ensures exactly one '/' between the path component of * \p baseUrl and \p path. The query component of \p baseUrl is ignored. */ - static QUrl makeRequestUrl(QUrl baseUrl, const QString& path, + static QUrl makeRequestUrl(QUrl baseUrl, const QByteArray &encodedPath, const QUrlQuery& query = {}); /*! Prepares the job for execution diff --git a/lib/jobs/syncjob.cpp b/lib/jobs/syncjob.cpp index 59a34ef3..9b1b46f0 100644 --- a/lib/jobs/syncjob.cpp +++ b/lib/jobs/syncjob.cpp @@ -10,7 +10,7 @@ static size_t jobId = 0; SyncJob::SyncJob(const QString& since, const QString& filter, int timeout, const QString& presence) : BaseJob(HttpVerb::Get, QStringLiteral("SyncJob-%1").arg(++jobId), - QStringLiteral("_matrix/client/r0/sync")) + "_matrix/client/r0/sync") { setLoggingCategory(SYNCJOB); QUrlQuery query; -- cgit v1.2.3 From f69e1c52246b986fb91f595ee0ee363e5343dbbb Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Wed, 29 Dec 2021 15:57:14 +0100 Subject: operation.h.mustache: Add QUOTIENT_API --- gtad/operation.h.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gtad') diff --git a/gtad/operation.h.mustache b/gtad/operation.h.mustache index f91dc66c..063f0bbd 100644 --- a/gtad/operation.h.mustache +++ b/gtad/operation.h.mustache @@ -16,7 +16,7 @@ namespace Quotient { /*!{{>docCommentSummary}}{{#description}} * {{_}}{{/description}} */ -class {{camelCaseOperationId}}Job : public BaseJob { +class QUOTIENT_API {{camelCaseOperationId}}Job : public BaseJob { public: {{#models}} // Inner data structures -- cgit v1.2.3 From abbab8d8f8c566bc2c9cdf766c6fbb11d978ca47 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 23 Jan 2022 17:11:22 +0100 Subject: Omittable: split out from util.h and refresh Improvements: - Quotient::lift() - a way to invoke a function on an optional (including Omittable) or a pointer if it's 'truthy'. Doesn't need enhanced function_traits<>, only the standard library; works on any number of arguments that can be dereferenced and casted to bool. - then() - the version of lift() as a member function. - edit() was renamed to ensure() (edit() might become a read-write counterpart of then() at some point). It's not really used across libQuotient codebase (or elsewhere) but is staying there just in case. It can also accept an initializer, removing the requirement of default-constructibility. - Quotient::merge() is simplified, with one universal implementation covering both Omittable/optional and plain values. - All that now lives in its dedicated pair of files, further decluttering util.h --- CMakeLists.txt | 1 + gtad/gtad.yaml | 2 +- lib/connection.h | 1 + lib/converters.h | 1 + lib/omittable.cpp | 34 +++++++++ lib/omittable.h | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/util.h | 141 ---------------------------------- 7 files changed, 261 insertions(+), 142 deletions(-) create mode 100644 lib/omittable.cpp create mode 100644 lib/omittable.h (limited to 'gtad') diff --git a/CMakeLists.txt b/CMakeLists.txt index 599424ab..13c8f591 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,6 +127,7 @@ list(APPEND lib_SRCS lib/quotient_common.h lib/quotient_export.h lib/function_traits.h lib/function_traits.cpp + lib/omittable.h lib/omittable.cpp lib/networkaccessmanager.h lib/networkaccessmanager.cpp lib/connectiondata.h lib/connectiondata.cpp lib/connection.h lib/connection.cpp diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index 943ac013..03c23886 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -45,7 +45,7 @@ analyzer: types: - +set: &UseOmittable useOmittable: - omittedValue: 'none' # Quotient::none in lib/util.h + omittedValue: 'none' # Quotient::none in lib/omittable.h +on: - integer: - int64: qint64 diff --git a/lib/connection.h b/lib/connection.h index 28688cc1..dc2eaad1 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -8,6 +8,7 @@ #include "ssosession.h" #include "qt_connection_util.h" #include "quotient_common.h" +#include "util.h" #include "csapi/login.h" #include "csapi/create_room.h" diff --git a/lib/converters.h b/lib/converters.h index 8eea1cd3..e7bc6898 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -3,6 +3,7 @@ #pragma once +#include "omittable.h" #include "util.h" #include diff --git a/lib/omittable.cpp b/lib/omittable.cpp new file mode 100644 index 00000000..245ae721 --- /dev/null +++ b/lib/omittable.cpp @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2021 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "omittable.h" + +// Omittable<> tests +using namespace Quotient; + +Omittable testFn(bool) { return 0; } +bool testFn2(int) { return false; } +static_assert( + std::is_same_v>().then(testFn)), + Omittable>); +static_assert( + std::is_same_v< + decltype(std::declval>().then_or(testFn, 0)), int>); +static_assert( + std::is_same_v>().then(testFn)), + Omittable>); +static_assert(std::is_same_v>() + .then(testFn2) + .then(testFn)), + Omittable>); +static_assert(std::is_same_v>() + .then(testFn) + .then_or(testFn2, false)), + bool>); + +constexpr auto visitTestFn(int, bool) { return false; } +static_assert( + std::is_same_v, decltype(lift(testFn2, Omittable()))>); +static_assert(std::is_same_v, + decltype(lift(visitTestFn, Omittable(), + Omittable()))>); diff --git a/lib/omittable.h b/lib/omittable.h new file mode 100644 index 00000000..b5efecf5 --- /dev/null +++ b/lib/omittable.h @@ -0,0 +1,223 @@ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + +#pragma once + +#include +#include + +namespace Quotient { + +template +class Omittable; + +constexpr auto none = std::nullopt; + +//! \brief Lift an operation into dereferenceable types (Omittables or pointers) +//! +//! This is a more generic version of Omittable::then() that extends to +//! an arbitrary number of arguments of any type that is dereferenceable (unary +//! operator*() can be applied to it) and (explicitly or implicitly) convertible +//! to bool. This allows to streamline checking for nullptr/none before applying +//! the operation on the underlying types. \p fn is only invoked if all \p args +//! are "truthy" (i.e. (... && bool(args)) == true). +//! \param fn A callable that should accept the types stored inside +//! Omittables/pointers passed in \p args +//! \return Always an Omittable: if \p fn returns another type, lift() wraps +//! it in an Omittable; if \p fn returns an Omittable, that return value +//! (or none) is returned as is. +template +inline auto lift(FnT&& fn, MaybeTs&&... args) +{ + return (... && bool(args)) + ? Omittable(std::invoke(std::forward(fn), *args...)) + : none; +} + +/** `std::optional` with tweaks + * + * The tweaks are: + * - streamlined assignment (operator=)/emplace()ment of values that can be + * used to implicitly construct the underlying type, including + * direct-list-initialisation, e.g.: + * \code + * struct S { int a; char b; } + * Omittable o; + * o = { 1, 'a' }; // std::optional would require o = S { 1, 'a' } + * \endcode + * - entirely deleted value(). The technical reason is that Xcode 10 doesn't + * have it; but besides that, value_or() or (after explicit checking) + * `operator*()`/`operator->()` are better alternatives within Quotient + * that doesn't practice throwing exceptions (as doesn't most of Qt). + * - disabled non-const lvalue operator*() and operator->(), as it's too easy + * to inadvertently cause a value change through them. + * - ensure() to provide a safe and explicit lvalue accessor instead of + * those above. Allows chained initialisation of nested Omittables: + * \code + * struct Inner { int member = 10; Omittable innermost; }; + * struct Outer { int anotherMember = 10; Omittable inner; }; + * Omittable o; // = { 10, std::nullopt }; + * o.ensure().inner.ensure().innermost.emplace(42); + * \endcode + * - merge() - a soft version of operator= that only overwrites its first + * operand with the second one if the second one is not empty. + * - then() and then_or() to streamline read-only interrogation in a "monadic" + * interface. + */ +template +class Omittable : public std::optional { +public: + using base_type = std::optional; + using value_type = std::decay_t; + + using std::optional::optional; + + // Overload emplace() and operator=() to allow passing braced-init-lists + // (the standard emplace() does direct-initialisation but + // not direct-list-initialisation). + using base_type::operator=; + Omittable& operator=(const value_type& v) + { + base_type::operator=(v); + return *this; + } + Omittable& operator=(value_type&& v) + { + base_type::operator=(std::move(v)); + return *this; + } + + using base_type::emplace; + T& emplace(const T& val) { return base_type::emplace(val); } + T& emplace(T&& val) { return base_type::emplace(std::move(val)); } + + // Use value_or() or check (with operator! or has_value) before accessing + // with operator-> or operator* + // The technical reason is that Xcode 10 has incomplete std::optional + // that has no value(); but using value() may also mean that you rely + // on the optional throwing an exception (which is not assumed practice + // throughout Quotient) or that you spend unnecessary CPU cycles on + // an extraneous has_value() check. + auto& value() = delete; + const auto& value() const = delete; + + template + value_type& ensure(U&& defaultValue = value_type {}) + { + return this->has_value() ? this->operator*() + : this->emplace(std::forward(defaultValue)); + } + value_type& ensure(const value_type& defaultValue) + { + return ensure<>(defaultValue); + } + value_type& ensure(value_type&& defaultValue) + { + return ensure<>(std::move(defaultValue)); + } + + //! Merge the value from another Omittable + //! \return true if \p other is not omitted and the value of + //! the current Omittable was different (or omitted), + //! in other words, if the current Omittable has changed; + //! false otherwise + template + auto merge(const std::optional& other) + -> std::enable_if_t, bool> + { + if (!other || (this->has_value() && **this == *other)) + return false; + this->emplace(*other); + return true; + } + + // Hide non-const lvalue operator-> and operator* as these are + // a bit too surprising: value() & doesn't lazy-create an object; + // and it's too easy to inadvertently change the underlying value. + + const value_type* operator->() const& { return base_type::operator->(); } + value_type* operator->() && { return base_type::operator->(); } + const value_type& operator*() const& { return base_type::operator*(); } + value_type& operator*() && { return base_type::operator*(); } + + // The below is inspired by the proposed std::optional monadic operations + // (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0798r6.html). + + //! \brief Lift a callable into the Omittable + //! + //! 'Lifting', as used in functional programming, means here invoking + //! a callable (e.g., a function) on the contents of the Omittable if it has + //! any and wrapping the returned value (that may be of a different type T2) + //! into a new Omittable\. If the current Omittable is empty, + //! the invocation is skipped altogether and Omittable\{none} is + //! returned instead. + //! \note if \p fn already returns an Omittable (i.e., it is a 'functor', + //! in functional programming terms), then() will not wrap another + //! Omittable around but will just return what \p fn returns. The + //! same doesn't hold for the parameter: if \p fn accepts an Omittable + //! you have to wrap it in another Omittable before calling then(). + //! \return `none` if the current Omittable has `none`; + //! otherwise, the Omittable returned from a call to \p fn + //! \tparam FnT a callable with \p T (or const T&) + //! returning Omittable, T2 is any supported type + //! \sa then_or, transform + template + auto then(FnT&& fn) const& + { + return lift(std::forward(fn), *this); + } + + //! \brief Lift a callable into the rvalue Omittable + //! + //! This is an rvalue overload for then(). + template + auto then(FnT&& fn) && + { + return lift(std::forward(fn), *this); + } + + //! \brief Lift a callable into the const lvalue Omittable, with a fallback + //! + //! This effectively does the same what then() does, except that it returns + //! a value of type returned by the callable, or the provided fallback value + //! if the current Omittable is empty. This is a typesafe version to apply + //! an operation on an Omittable without having to deal with another + //! Omittable afterwards. + template + auto then_or(FnT&& fn, FallbackT&& fallback) const& + { + return then(std::forward(fn)) + .value_or(std::forward(fallback)); + } + + //! \brief Lift a callable into the rvalue Omittable, with a fallback + //! + //! This is an overload for functions that accept rvalue + template + auto then_or(FnT&& fn, FallbackT&& fallback) && + { + return then(std::forward(fn)) + .value_or(std::forward(fallback)); + } +}; + +template +Omittable(T&&) -> Omittable; + +//! \brief Merge the value from an optional +//! This is an adaptation of Omittable::merge() to the case when the value +//! on the left hand side is not an Omittable. +//! \return true if \p rhs is not omitted and the \p lhs value was different, +//! in other words, if \p lhs has changed; +//! false otherwise +template +inline auto merge(T1& lhs, const std::optional& rhs) + -> std::enable_if_t, bool> +{ + if (!rhs || lhs == *rhs) + return false; + lhs = *rhs; + return true; +} + +} // namespace Quotient diff --git a/lib/util.h b/lib/util.h index 3505b62f..753eb1ea 100644 --- a/lib/util.h +++ b/lib/util.h @@ -9,10 +9,8 @@ #include #include -#include #include #include -#include #ifndef Q_DISABLE_MOVE // Q_DISABLE_MOVE was introduced in Q_VERSION_CHECK(5,13,0) @@ -52,145 +50,6 @@ struct HashQ { template using UnorderedMap = std::unordered_map>; -namespace _impl { - template - constexpr auto IsOmittableValue = false; - template - constexpr auto IsOmittable = IsOmittableValue>; -} - -constexpr auto none = std::nullopt; - -/** `std::optional` with tweaks - * - * The tweaks are: - * - streamlined assignment (operator=)/emplace()ment of values that can be - * used to implicitly construct the underlying type, including - * direct-list-initialisation, e.g.: - * \code - * struct S { int a; char b; } - * Omittable o; - * o = { 1, 'a' }; // std::optional would require o = S { 1, 'a' } - * \endcode - * - entirely deleted value(). The technical reason is that Xcode 10 doesn't - * have it; but besides that, value_or() or (after explicit checking) - * `operator*()`/`operator->()` are better alternatives within Quotient - * that doesn't practice throwing exceptions (as doesn't most of Qt). - * - disabled non-const lvalue operator*() and operator->(), as it's too easy - * to inadvertently cause a value change through them. - * - edit() to provide a safe and explicit lvalue accessor instead of those - * above. Requires the underlying type to be default-constructible. - * Allows chained initialisation of nested Omittables: - * \code - * struct Inner { int member = 10; Omittable innermost; }; - * struct Outer { int anotherMember = 10; Omittable inner; }; - * Omittable o; // = { 10, std::nullopt }; - * o.edit().inner.edit().innermost.emplace(42); - * \endcode - * - merge() - a soft version of operator= that only overwrites its first - * operand with the second one if the second one is not empty. - */ -template -class Omittable : public std::optional { -public: - using base_type = std::optional; - using value_type = std::decay_t; - - using std::optional::optional; - - // Overload emplace() and operator=() to allow passing braced-init-lists - // (the standard emplace() does direct-initialisation but - // not direct-list-initialisation). - using base_type::operator=; - Omittable& operator=(const value_type& v) - { - base_type::operator=(v); - return *this; - } - Omittable& operator=(value_type&& v) - { - base_type::operator=(v); - return *this; - } - using base_type::emplace; - T& emplace(const T& val) { return base_type::emplace(val); } - T& emplace(T&& val) { return base_type::emplace(std::move(val)); } - - // use value_or() or check (with operator! or has_value) before accessing - // with operator-> or operator* - // The technical reason is that Xcode 10 has incomplete std::optional - // that has no value(); but using value() may also mean that you rely - // on the optional throwing an exception (which is not assumed practice - // throughout Quotient) or that you spend unnecessary CPU cycles on - // an extraneous has_value() check. - value_type& value() = delete; - const value_type& value() const = delete; - value_type& edit() - { - return this->has_value() ? base_type::operator*() : this->emplace(); - } - - [[deprecated("Use '!o' or '!o.has_value()' instead of 'o.omitted()'")]] - bool omitted() const - { - return !this->has_value(); - } - - //! Merge the value from another Omittable - //! \return true if \p other is not omitted and the value of - //! the current Omittable was different (or omitted), - //! in other words, if the current Omittable has changed; - //! false otherwise - template - auto merge(const Omittable& other) - -> std::enable_if_t, bool> - { - if (!other || (this->has_value() && **this == *other)) - return false; - emplace(*other); - return true; - } - - // Hide non-const lvalue operator-> and operator* as these are - // a bit too surprising: value() & doesn't lazy-create an object; - // and it's too easy to inadvertently change the underlying value. - - const value_type* operator->() const& { return base_type::operator->(); } - value_type* operator->() && { return base_type::operator->(); } - const value_type& operator*() const& { return base_type::operator*(); } - value_type& operator*() && { return base_type::operator*(); } -}; -template -Omittable(T&&) -> Omittable; - -namespace _impl { - template - constexpr auto IsOmittableValue> = true; -} - -template -inline auto merge(Omittable& lhs, T2&& rhs) -{ - return lhs.merge(std::forward(rhs)); -} - -//! \brief Merge the value from an Omittable -//! This is an adaptation of Omittable::merge() to the case when the value -//! on the left hand side is not an Omittable. -//! \return true if \p rhs is not omitted and the \p lhs value was different, -//! in other words, if \p lhs has changed; -//! false otherwise -template -inline auto merge(T1& lhs, const Omittable& rhs) - -> std::enable_if_t - && std::is_convertible_v, bool> -{ - if (!rhs || lhs == *rhs) - return false; - lhs = *rhs; - return true; -} - constexpr auto operator"" _ls(const char* s, std::size_t size) { return QLatin1String(s, int(size)); -- cgit v1.2.3 From 3c6ca3c89d7b1a972d50ec4eb0b42ab350771f72 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 31 May 2022 17:36:17 +0200 Subject: Update gtad.yml to match v3 API definitions Also: use quotient-im/matrix-spec main branch again, now that it has adjusted definitions; drop un(der)used partials --- .github/workflows/ci.yml | 3 --- gtad/gtad.yaml | 17 +++++------------ 2 files changed, 5 insertions(+), 15 deletions(-) (limited to 'gtad') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bea9f436..9b9383db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -180,9 +180,6 @@ jobs: working-directory: ${{ runner.workspace }} run: | git clone https://github.com/quotient-im/matrix-spec.git - pushd matrix-spec - git checkout fixcompilation - popd git clone --recursive https://github.com/KitsuneRal/gtad.git cmake -S gtad -B build/gtad $CMAKE_ARGS -DBUILD_SHARED_LIBS=OFF cmake --build build/gtad diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index 03c23886..e8d4ba35 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -85,9 +85,8 @@ analyzer: imports: '"events/eventloader.h"' +on: - /state_event.yaml$/: StateEventPtr - - /room_event.yaml$/: RoomEventPtr - - /event.yaml$/: EventPtr - - /m\.room\.member/: void # Skip resolving; see EventsArray<> below + - /(room|client)_event.yaml$/: RoomEventPtr + - /event(_without_room_id)?.yaml$/: EventPtr - +set: # This renderer actually applies to all $ref things _importRenderer: '"{{#segments}}{{_}}{{#_join}}/{{/_join}}{{/segments}}.h"' @@ -115,12 +114,9 @@ analyzer: - /^Notification|Result$/: type: "std::vector<{{1}}>" imports: '"events/eventloader.h"' - - /m\.room\.member/: # Only used in an array (see also above) - type: "EventsArray" - imports: '"events/roommemberevent.h"' - /state_event.yaml$/: StateEvents - - /room_event.yaml$/: RoomEvents - - /event.yaml$/: Events + - /(room|client)_event.yaml$/: RoomEvents + - /event(_without_room_id)?.yaml$/: Events - //: "QVector<{{1}}>" - map: # `additionalProperties` in OpenAPI - RoomState: @@ -164,11 +160,8 @@ mustache: qualifiedMaybeOmittableType: "{{>openOmittable}}{{dataType.qualifiedName}}{{>closeOmittable}}" - ref: "{{#avoidCopy}}&{{/avoidCopy}}{{#moveOnly}}&&{{/moveOnly}}" maybeCrefType: - "{{#avoidCopy}}const {{/avoidCopy}}{{>maybeOmittableType}}{{>ref}}" - qualifiedMaybeCrefType: - "{{#avoidCopy}}const {{/avoidCopy}}{{>qualifiedMaybeOmittableType}}{{>ref}}" + "{{#avoidCopy}}const {{/avoidCopy}}{{>maybeOmittableType}}{{#avoidCopy}}&{{/avoidCopy}}" maybeCrefJsonObject: "{{^propertyMap}}const QJsonObject&{{/propertyMap}}\ -- cgit v1.2.3 From fed831820965ad5654317d5e7df18c23fa75de20 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 31 May 2022 16:30:22 +0200 Subject: gtad.yaml (again): shortcut OneTimeKeys This requires OneTimeKeys in keys.yaml to be marked as such (done in quotient-im/matrix-spec but it's not there in matrix-org/matrix-spec). --- gtad/gtad.yaml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'gtad') diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index e8d4ba35..b1c143b6 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -106,6 +106,9 @@ analyzer: # imports: '"csapi/definitions/sync_filter.h"' # - getFilter<: *Filter - RoomFilter: # A structure inside Filter, same story as with *_filter.yaml + - OneTimeKeys: + type: OneTimeKeys + imports: '"e2ee/e2ee.h"' - //: *UseOmittable - array: - string: QStringList -- cgit v1.2.3 From de3a446b7b005ac57edb422eced7eec252ed3a92 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 6 Jun 2022 13:38:32 +0200 Subject: GTAD: inline public_rooms_chunk.yaml Also: drop inlining PublicRoomResponse by the name because it's already inlined by $ref before that. This configuration needs the latest GTAD (revision 51c53ed3) to work correctly; earlier GTAD will produce FTBFS code. --- gtad/gtad.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gtad') diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index b1c143b6..2d004cbc 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -97,10 +97,10 @@ analyzer: title: MsisdnValidationData - /_filter.yaml$/: # Event/RoomEventFilters do NOT need Omittable<> - /public_rooms_response.yaml$/: { _inline: true } + - /public_rooms_chunk.yaml$/: { _inline: true } - //: *UseOmittable # Also apply "avoidCopy" to all other ref'ed types - schema: - getTurnServer<: *QJsonObject # It's used as an opaque JSON object - - PublicRoomResponse: { _inline: true } # - defineFilter>: &Filter # Force folding into a structure # type: Filter # imports: '"csapi/definitions/sync_filter.h"' -- cgit v1.2.3 From f10259aa3b5051e4b36b4e0fd2f2d0db06fb7c20 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 6 Jun 2022 13:55:15 +0200 Subject: Add GTAD as a submodule Code generation in libQuotient is pretty sensitive to GTAD version (or even a particular commit at times); so it makes sense to have GTAD as a submodule in order to control the revision CI uses. (amended with the GTAD commit that uses the right yaml-cpp commit) --- .gitmodules | 3 +++ gtad/gtad | 1 + 2 files changed, 4 insertions(+) create mode 160000 gtad/gtad (limited to 'gtad') diff --git a/.gitmodules b/.gitmodules index e69de29b..f3aef316 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "gtad/gtad"] + path = gtad/gtad + url = https://github.com/quotient-im/gtad.git diff --git a/gtad/gtad b/gtad/gtad new file mode 160000 index 00000000..fcc8e0f2 --- /dev/null +++ b/gtad/gtad @@ -0,0 +1 @@ +Subproject commit fcc8e0f28367f37890db9cfa5e96d08d599b36fc -- cgit v1.2.3 From 40311ec08a88de821884197bc60f1b48748cbbb3 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 11 Jun 2022 16:51:28 +0200 Subject: gtad.yaml: more clarifying comments --- gtad/gtad.yaml | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'gtad') diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index 2d004cbc..12a27c06 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -88,7 +88,8 @@ analyzer: - /(room|client)_event.yaml$/: RoomEventPtr - /event(_without_room_id)?.yaml$/: EventPtr - +set: - # This renderer actually applies to all $ref things + # This renderer applies to everything actually $ref'ed + # (not substituted) _importRenderer: '"{{#segments}}{{_}}{{#_join}}/{{/_join}}{{/segments}}.h"' +on: - '/^(\./)?definitions/request_email_validation.yaml$/': @@ -96,7 +97,20 @@ analyzer: - '/^(\./)?definitions/request_msisdn_validation.yaml$/': title: MsisdnValidationData - /_filter.yaml$/: # Event/RoomEventFilters do NOT need Omittable<> + + # Despite being used in two calls, it's more practical to have those + # fields available as getters right from the respective job classes - /public_rooms_response.yaml$/: { _inline: true } + + # list_public_rooms.yaml (via public_rooms_response.yaml) and + # space_hierarchy.yaml use public_rooms_chunk.yaml as a common base + # structure, adding (space_hiearchy) or overriding + # (public_rooms_response) fields for their purposes. The spec text + # confusingly ends up with having two different structures named + # "PublicRoomsChunk". To make sure the types are distinct in + # libQuotient, this common base is inlined into the actually used + # data structures (that have distinct names) defined + # in space_hierarchy.h and public_rooms_response.h, respectively - /public_rooms_chunk.yaml$/: { _inline: true } - //: *UseOmittable # Also apply "avoidCopy" to all other ref'ed types - schema: @@ -117,17 +131,17 @@ analyzer: - /^Notification|Result$/: type: "std::vector<{{1}}>" imports: '"events/eventloader.h"' - - /state_event.yaml$/: StateEvents - - /(room|client)_event.yaml$/: RoomEvents - - /event(_without_room_id)?.yaml$/: Events + - /state_event.yaml$/: StateEvents # 'imports' already set under $ref + - /(room|client)_event.yaml$/: RoomEvents # ditto + - /event(_without_room_id)?.yaml$/: Events # ditto - //: "QVector<{{1}}>" - map: # `additionalProperties` in OpenAPI - RoomState: type: "UnorderedMap" moveOnly: - /.+/: "QHash" - - //: QVariantHash - - variant: # A sequence `type` (multitype) in OpenAPI + - //: QVariantHash # QJsonObject?.. + - variant: # A sequence `type` or a 'oneOf' group in OpenAPI - /^string,null|null,string$/: *QString - //: QVariant -- cgit v1.2.3 From c11dc723e8b5170e6fd3750cffe5990f13772cdd Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 9 Jun 2022 10:22:50 +0200 Subject: gtad: update submodule --- gtad/gtad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gtad') diff --git a/gtad/gtad b/gtad/gtad index fcc8e0f2..9e89412e 160000 --- a/gtad/gtad +++ b/gtad/gtad @@ -1 +1 @@ -Subproject commit fcc8e0f28367f37890db9cfa5e96d08d599b36fc +Subproject commit 9e89412ec0c8d792e525a660940ab12d3fa5cf9c -- cgit v1.2.3 From 743909a728e22f52f7531b0f98395f0361cd0fd3 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 11 Jun 2022 19:41:59 +0200 Subject: gtad.yaml: Treat child rooms state as events --- gtad/gtad.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'gtad') diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index 12a27c06..f4ad122e 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -119,6 +119,7 @@ analyzer: # type: Filter # imports: '"csapi/definitions/sync_filter.h"' # - getFilter<: *Filter + - StrippedChildStateEvent: void # only used in an array, see below - RoomFilter: # A structure inside Filter, same story as with *_filter.yaml - OneTimeKeys: type: OneTimeKeys @@ -128,8 +129,9 @@ analyzer: - string: QStringList - +set: { moveOnly: } +on: - - /^Notification|Result$/: - type: "std::vector<{{1}}>" + - /^Notification|Result|ChildRoomsChunk$/: "std::vector<{{1}}>" + - StrippedChildStateEvent: + type: StateEvents imports: '"events/eventloader.h"' - /state_event.yaml$/: StateEvents # 'imports' already set under $ref - /(room|client)_event.yaml$/: RoomEvents # ditto -- cgit v1.2.3 From 130c3ee975fe5312e97080cd978c0807b2611a68 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 11 Jun 2022 21:33:21 +0200 Subject: gtad.yaml: Drop deprecated home_server field from login/register --- gtad/gtad.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gtad') diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index f4ad122e..0bec3b7a 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -29,6 +29,8 @@ analyzer: login>/user: "" login>/medium: "" login>/address: "" + login -- cgit v1.2.3 From 3a2e7f19c97289fb962b1c0ba4439870bbd0f31d Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 11 Jun 2022 17:03:06 +0200 Subject: gtad: update submodule (again) --- gtad/gtad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gtad') diff --git a/gtad/gtad b/gtad/gtad index 9e89412e..9ea32fb7 160000 --- a/gtad/gtad +++ b/gtad/gtad @@ -1 +1 @@ -Subproject commit 9e89412ec0c8d792e525a660940ab12d3fa5cf9c +Subproject commit 9ea32fb74767a62a3a0d27b3b181e8c18fb0c691 -- cgit v1.2.3 From 10867950474a360426685ad888237a5542b0cfac Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 16 Jun 2022 13:28:35 +0200 Subject: operation.cpp.mustache: streamline RequestData construction That `std::move(_data)` never worked because the passed object is a precursor to RequestData, and RequestData always takes things by const-ref or by value, never by rvalue. Also, explicit mention of RequestData is unnecessary, as its constructors are implicit by design. --- gtad/operation.cpp.mustache | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'gtad') diff --git a/gtad/operation.cpp.mustache b/gtad/operation.cpp.mustache index 3d26ec73..4b75434c 100644 --- a/gtad/operation.cpp.mustache +++ b/gtad/operation.cpp.mustache @@ -34,20 +34,20 @@ QUrl {{camelCaseOperationId}}Job::makeRequestUrl(QUrl baseUrl{{#allParams?}}, { {{#headerParams}} setRequestHeader("{{baseName}}", {{paramName}}.toLatin1()); {{/headerParams}}{{#inlineBody}}{{^propertyMap}}{{^bodyParams?}} - setRequestData(RequestData({{#consumesNonJson?}}{{nameCamelCase}}{{/consumesNonJson? - }}{{^consumesNonJson?}}toJson({{nameCamelCase}}){{/consumesNonJson?}})); + setRequestData({ {{#consumesNonJson?}}{{nameCamelCase}}{{/consumesNonJson? + }}{{^consumesNonJson?}}toJson({{nameCamelCase}}){{/consumesNonJson?}} }); {{/bodyParams?}}{{/propertyMap}}{{/inlineBody }}{{^consumesNonJson?}}{{#bodyParams?}} - QJsonObject _data; + QJsonObject _dataJson; {{#propertyMap}} - fillJson(_data, {{nameCamelCase}}); + fillJson(_dataJson, {{nameCamelCase}}); {{/propertyMap}}{{#inlineBody}} - fillJson<{{>maybeOmittableType}}>(_data, {{paramName}}); + fillJson<{{>maybeOmittableType}}>(_dataJson, {{paramName}}); {{/inlineBody}}{{#bodyParams}} - addParam<{{^required?}}IfNotEmpty{{/required?}}>(_data, + addParam<{{^required?}}IfNotEmpty{{/required?}}>(_dataJson, QStringLiteral("{{baseName}}"), {{paramName}}); {{/bodyParams}} - setRequestData(std::move(_data)); + setRequestData({ _dataJson }); {{/bodyParams?}}{{/consumesNonJson?}}{{#producesNonJson?}} setExpectedContentTypes({ {{#produces}}"{{_}}"{{>cjoin}}{{/produces}} }); {{/producesNonJson?}}{{^producesNonJson? -- cgit v1.2.3 From 896f46d4cf08ab05611b72edeb6c4d70e597342f Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Fri, 12 Aug 2022 17:07:20 +0200 Subject: GTAD: Stop using eventloader.h in generated files --- gtad/gtad.yaml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'gtad') diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml index 0bec3b7a..4b05d2d4 100644 --- a/gtad/gtad.yaml +++ b/gtad/gtad.yaml @@ -84,11 +84,16 @@ analyzer: - $ref: - +set: moveOnly: - imports: '"events/eventloader.h"' +on: - - /state_event.yaml$/: StateEventPtr - - /(room|client)_event.yaml$/: RoomEventPtr - - /event(_without_room_id)?.yaml$/: EventPtr + - /state_event.yaml$/: + type: StateEventPtr + imports: '"events/stateevent.h"' + - /(room|client)_event.yaml$/: + type: RoomEventPtr + imports: '"events/roomevent.h"' + - /event(_without_room_id)?.yaml$/: + type: EventPtr + imports: '"events/event.h"' - +set: # This renderer applies to everything actually $ref'ed # (not substituted) @@ -132,12 +137,11 @@ analyzer: - +set: { moveOnly: } +on: - /^Notification|Result|ChildRoomsChunk$/: "std::vector<{{1}}>" - - StrippedChildStateEvent: + - /^StrippedChildStateEvent$|state_event.yaml$/: type: StateEvents - imports: '"events/eventloader.h"' - - /state_event.yaml$/: StateEvents # 'imports' already set under $ref - - /(room|client)_event.yaml$/: RoomEvents # ditto - - /event(_without_room_id)?.yaml$/: Events # ditto + imports: '"events/stateevent.h"' # For StrippedChildStateEvent + - /(room|client)_event.yaml$/: RoomEvents + - /event(_without_room_id)?.yaml$/: Events - //: "QVector<{{1}}>" - map: # `additionalProperties` in OpenAPI - RoomState: -- cgit v1.2.3