aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKitsune Ral <Kitsune-Ral@users.sf.net>2020-06-06 20:47:56 +0200
committerKitsune Ral <Kitsune-Ral@users.sf.net>2020-06-07 19:44:33 +0200
commita0430b1fb722a77ad7cbd28f181727d46d92b3a2 (patch)
treead2930c25107ec51c1134f2b68490a223d5debfc
parent21c04d5b035cec0b6378e60acc93523f52c1c973 (diff)
downloadlibquotient-a0430b1fb722a77ad7cbd28f181727d46d92b3a2.tar.gz
libquotient-a0430b1fb722a77ad7cbd28f181727d46d92b3a2.zip
gtad/*: optimise and use latest GTAD features
- The generated code is updated to be compatible with the BaseJob changes introduced in the previous commit. This includes greatly reducing the number of header files that have to be explicitly #included, as basejob.h now #includes converters.h. Also, thanks to the changes in BaseJob, none of generated job classes needs a pimpl Private class. - gtad/template.*.mustache files are replaced with data.h.mustache for data structures (entirely defined in header files from now on) and operation.*.mustache for API operations (also massively moved to header files, possibly also becoming header-only in the future). - New variable-dropping and title-overring features in GTAD 0.7 allow to use the upstream matrix-doc repo to generate the code. - CMakeLists.txt makes use of file globbing with CONFIGURE_DEPENDS where possible to alleviate build reconfiguration after a GTAD call.
-rw-r--r--CMakeLists.txt51
-rw-r--r--gtad/data.h.mustache53
-rw-r--r--gtad/gtad.yaml102
-rw-r--r--gtad/operation.cpp.mustache58
-rw-r--r--gtad/operation.h.mustache128
-rw-r--r--gtad/template.cpp.mustache182
-rw-r--r--gtad/template.h.mustache119
-rw-r--r--libquotient.pri4
8 files changed, 336 insertions, 361 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1e336673..c61c2682 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -184,21 +184,21 @@ set(lib_SRCS
)
set(CSAPI_DIR csapi)
+set(FULL_CSAPI_DIR lib/${CSAPI_DIR})
set(ASAPI_DEF_DIR application-service/definitions)
set(ISAPI_DEF_DIR identity/definitions)
-foreach (D ${CSAPI_DIR} ${CSAPI_DIR}/definitions
- ${CSAPI_DIR}/definitions/wellknown ${ASAPI_DEF_DIR} ${ISAPI_DEF_DIR})
- aux_source_directory(lib/${D} api_SRCS)
-endforeach()
+if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.12.0")
+ set(add_CONFIGURE_DEPENDS "CONFIGURE_DEPENDS")
+endif()
+file(GLOB_RECURSE api_SRCS ${add_CONFIGURE_DEPENDS} ${FULL_CSAPI_DIR}/*.cpp)
# Make no mistake: CMake cannot run gtad first and then populate the list of
-# resulting api_SRCS files. In other words, placing the above foreach after
-# the custom targets definition won't bring the desired result:
+# resulting api_SRCS files. In other words, placing the above statement after
+# the add_custom_target() call below won't bring the desired result:
# CMake will execute it at cmake invocation and gtad will only run later
# when building the update-api target. If you see that gtad has created
-# new files you have to re-run cmake.
-# TODO: check `file(GLOB_RECURSE ... CONFIGURE_DEPENDS)` (from CMake 3.14)
+# new files you have to re-run cmake. CONFIGURE_DEPENDS somewhat helps that.
if (MATRIX_DOC_PATH AND GTAD_PATH)
set(FULL_CSAPI_SRC_DIR ${ABS_API_DEF_PATH}/client-server)
file(GLOB_RECURSE API_DEFS RELATIVE ${PROJECT_SOURCE_DIR}
@@ -206,7 +206,7 @@ if (MATRIX_DOC_PATH AND GTAD_PATH)
${ABS_API_DEF_PATH}/${ASAPI_DEF_DIR}/*.yaml
${ABS_API_DEF_PATH}/${ISAPI_DEF_DIR}/*.yaml
)
- add_custom_target(update-api
+ add_custom_target(generate-unformatted-api
${ABS_GTAD_PATH} --config ../gtad/gtad.yaml --out ${CSAPI_DIR}
${FULL_CSAPI_SRC_DIR}
old_sync.yaml- room_initial_sync.yaml- # deprecated
@@ -214,25 +214,30 @@ if (MATRIX_DOC_PATH AND GTAD_PATH)
sync.yaml- # we have a better handcrafted implementation
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/lib
SOURCES gtad/gtad.yaml
- gtad/template.h.mustache
- gtad/template.cpp.mustache
+ gtad/data.h.mustache
+ gtad/operation.h.mustache
+ gtad/operation.cpp.mustache
${API_DEFS}
VERBATIM
)
if (ABS_CLANG_FORMAT)
- # TODO: list(TRANSFORM) is available from CMake 3.12
- foreach (S ${api_SRCS})
- string (REGEX REPLACE ".cpp$" ".h" H ${S})
- list(APPEND api_HDRS ${H})
- endforeach()
set(CLANG_FORMAT_ARGS -i -sort-includes ${CLANG_FORMAT_ARGS})
- add_custom_command(TARGET update-api POST_BUILD
- COMMAND ${ABS_CLANG_FORMAT} ${CLANG_FORMAT_ARGS} ${api_SRCS}
- COMMAND ${ABS_CLANG_FORMAT} ${CLANG_FORMAT_ARGS} ${api_HDRS}
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- VERBATIM
- COMMENT "Formatting files"
- )
+ # FIXME: the list of files should be produced after GTAD has run.
+ # For now it's produced at CMake invocation; and if file() doesn't file
+ # any files clang-format chokes; also,
+ file(GLOB_RECURSE api_ALL_SRCS ${add_CONFIGURE_DEPENDS}
+ ${FULL_CSAPI_DIR}/*.*
+ lib/${ASAPI_DEF_DIR}/*.*
+ lib/${ISAPI_DEF_DIR}/*.*)
+ if (api_ALL_SRCS)
+ add_custom_target(format-api
+ ${ABS_CLANG_FORMAT} ${CLANG_FORMAT_ARGS} ${api_ALL_SRCS}
+ DEPENDS generate-unformatted-api
+ VERBATIM)
+ add_custom_target(update-api DEPENDS format-api)
+ else()
+ add_custom_target(update-api DEPENDS generate-unformatted-api)
+ endif()
endif()
endif()
diff --git a/gtad/data.h.mustache b/gtad/data.h.mustache
new file mode 100644
index 00000000..32ea85ee
--- /dev/null
+++ b/gtad/data.h.mustache
@@ -0,0 +1,53 @@
+{{>preamble}}
+#pragma once
+
+#include "converters.h"
+{{#imports}}
+#include {{_}}{{/imports}}
+
+namespace Quotient {
+{{#models}}
+ {{#model}}
+{{>docCommentShort}}
+struct {{name}}{{#parents?}} : {{#parents}}{{name}}{{>cjoin}}{{/parents}}{{/parents?}}
+{ {{#vars}}
+
+ {{>docCommentShort}}
+ {{>maybeOmittableType}} {{nameCamelCase}};
+ {{/vars}}{{#propertyMap}}
+
+ {{>docCommentShort}}
+ {{>maybeOmittableType}} {{nameCamelCase}};
+ {{/propertyMap}}
+};
+
+template <> struct JsonObjectConverter<{{name}}>
+{
+ {{#in?}}
+ static void dumpTo(QJsonObject& jo, const {{name}}& pod)
+ { {{#propertyMap}}
+ fillJson(jo, pod.{{nameCamelCase}});
+ {{/propertyMap}}{{#parents}}
+ fillJson<{{name}}>(jo, pod);
+ {{/parents}}{{#vars}}
+ addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo,
+ QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}});
+ {{/vars}}
+ }
+ {{/in?}}
+ {{#out?}}
+ static void fillFrom({{>maybeCrefJsonObject}} jo, {{name}}& pod)
+ { {{#parents}}
+ fillFromJson<{{qualifiedName}}>(jo, pod);
+ {{/parents}}{{#vars}}
+ fromJson(jo.{{>takeOrValue}}("{{baseName}}"_ls), pod.{{nameCamelCase}});
+ {{/vars}}{{#propertyMap}}
+ fromJson(jo, pod.{{nameCamelCase}});
+ {{/propertyMap}}
+ }
+ {{/out?}}
+};
+
+ {{/model}}
+{{/models}}
+} // namespace Quotient
diff --git a/gtad/gtad.yaml b/gtad/gtad.yaml
index 51f9e26b..045f5f35 100644
--- a/gtad/gtad.yaml
+++ b/gtad/gtad.yaml
@@ -15,6 +15,11 @@ analyzer:
m.change_password: changePassword
m.room_versions: roomVersions
AuthenticationData/additionalProperties: authInfo
+ /\b(Location|Protocol|User)$/: 'ThirdParty$&'
+ # These parameters are deprecated and unused in Quotient; so drop them
+ login>/user: ""
+ login>/medium: ""
+ login>/address: ""
# Structure inside `types`:
# - swaggerType: <targetTypeSpec>
@@ -31,8 +36,7 @@ analyzer:
types:
- +set: &UseOmittable
useOmittable:
- imports: [ '"converters.h"' ]
- omittedValue: 'none' # See `none` in converters.h
+ omittedValue: 'none' # Quotient::none in lib/util.h
+on:
- integer:
- int64: qint64
@@ -52,11 +56,9 @@ analyzer:
- date:
type: QDate
initializer: QDate::fromString("{{defaultValue}}")
- imports: <QtCore/QDate>
- dateTime:
type: QDateTime
initializer: QDateTime::fromString("{{defaultValue}}")
- imports: <QtCore/QDateTime>
- //: &QString
type: QString
initializer: QStringLiteral("{{defaultValue}}")
@@ -64,7 +66,7 @@ analyzer:
- file: *ByteStream
- +set: { avoidCopy: }
+on:
- - object: &QJsonObject { type: QJsonObject, imports: <QtCore/QJsonObject> }
+ - object: &QJsonObject { type: QJsonObject }
- $ref:
- +set: { moveOnly: }
+on:
@@ -74,10 +76,16 @@ analyzer:
{ type: RoomEventPtr, imports: '"events/eventloader.h"' }
- /event.yaml$/:
{ type: EventPtr, imports: '"events/eventloader.h"' }
- - /m\.room\.member$/: pass # This $ref is only used in an array, see below
+ - /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<>
- //: *UseOmittable # Also apply "avoidCopy" to all other ref'ed types
- - schema: # Properties of inline structure definitions
- - TurnServerCredentials: *QJsonObject # Because it's used as is
+ - schema:
+ - getTurnServer<: *QJsonObject # It's used as an opaque JSON object
+ - RoomFilter: # A structure inside Filter, same story as with other filters
- //: *UseOmittable
- array:
- string: QStringList
@@ -86,27 +94,23 @@ analyzer:
- /^Notification|Result$/:
type: "std::vector<{{1}}>"
imports: '"events/eventloader.h"'
- - /m\.room\.member$/:
+ - /m\.room\.member$/: # Only used in an array (see also above)
type: "EventsArray<RoomMemberEvent>"
imports: '"events/roommemberevent.h"'
- /state_event.yaml$/: StateEvents
- /room_event.yaml$/: RoomEvents
- /event.yaml$/: Events
- - //: { type: "QVector<{{1}}>", imports: <QtCore/QVector> }
+ - //: "QVector<{{1}}>"
- map: # `additionalProperties` in OpenAPI
- RoomState:
type: "UnorderedMap<QString, {{1}}>"
moveOnly:
- imports: '"util.h"'
- /.+/:
type: "QHash<QString, {{1}}>"
- imports: <QtCore/QHash>
- - //:
- type: QVariantHash
- imports: <QtCore/QVariant>
+ - //: QVariantHash
- variant: # A sequence `type` (multitype) in OpenAPI
- /^string,null|null,string$/: *QString
- - //: { type: QVariant, imports: <QtCore/QVariant> }
+ - //: QVariant
#operations:
@@ -127,43 +131,75 @@ mustache:
initializer: '{{defaultValue}}'
cjoin: '{{#hasMore}}, {{/hasMore}}'
- openOmittable: "{{^required?}}{{#useOmittable}}{{^defaultValue}}Omittable<{{/defaultValue}}{{/useOmittable}}{{/required?}}"
- closeOmittable: "{{^required?}}{{#useOmittable}}{{^defaultValue}}>{{/defaultValue}}{{/useOmittable}}{{/required?}}"
+ openOmittable:
+ "{{^required?}}{{#useOmittable}}\
+ {{^defaultValue}}Omittable<{{/defaultValue}}\
+ {{/useOmittable}}{{/required?}}"
+ closeOmittable:
+ "{{^required?}}{{#useOmittable}}\
+ {{^defaultValue}}>{{/defaultValue}}\
+ {{/useOmittable}}{{/required?}}"
maybeOmittableType: "{{>openOmittable}}{{dataType.name}}{{>closeOmittable}}"
- qualifiedMaybeOmittableType: "{{>openOmittable}}{{dataType.qualifiedName}}{{>closeOmittable}}"
+ qualifiedMaybeOmittableType:
+ "{{>openOmittable}}{{dataType.qualifiedName}}{{>closeOmittable}}"
- maybeCrefType: "{{#avoidCopy}}const {{/avoidCopy}}{{>maybeOmittableType}}{{#avoidCopy}}&{{/avoidCopy}}{{#moveOnly}}&&{{/moveOnly}}"
+ ref: "{{#avoidCopy}}&{{/avoidCopy}}{{#moveOnly}}&&{{/moveOnly}}"
+ maybeCrefType:
+ "{{#avoidCopy}}const {{/avoidCopy}}{{>maybeOmittableType}}{{>ref}}"
qualifiedMaybeCrefType:
- "{{#avoidCopy}}const {{/avoidCopy}}{{>qualifiedMaybeOmittableType}}{{#avoidCopy}}&{{/avoidCopy}}{{#moveOnly}}&&{{/moveOnly}}"
+ "{{#avoidCopy}}const {{/avoidCopy}}{{>qualifiedMaybeOmittableType}}{{>ref}}"
- maybeCrefJsonObject: "{{^propertyMap}}const QJsonObject&{{/propertyMap}}{{#propertyMap}}QJsonObject{{/propertyMap}}"
- takeOrValue: "{{#propertyMap}}take{{/propertyMap}}{{^propertyMap}}value{{/propertyMap}}"
+ maybeCrefJsonObject:
+ "{{^propertyMap}}const QJsonObject&{{/propertyMap}}\
+ {{#propertyMap}}QJsonObject{{/propertyMap}}"
- initializeDefaultValue: "{{#defaultValue}}{{>initializer}}{{/defaultValue}}{{^defaultValue}}{{>omittedValue}}{{/defaultValue}}"
- joinedParamDecl: '{{>maybeCrefType}} {{paramName}}{{^required?}} = {{>initializeDefaultValue}}{{/required?}}{{>cjoin}}'
- joinedParamDef: '{{>maybeCrefType}} {{paramName}}{{>cjoin}}'
- passQueryParams: '{{#queryParams}}{{paramName}}{{>cjoin}}{{/queryParams}}'
+ takeOrValue:
+ "{{#propertyMap}}take{{/propertyMap}}{{^propertyMap}}value{{/propertyMap}}"
+ takeOrLoad: "{{#moveOnly}}take{{/moveOnly}}{{^moveOnly}}load{{/moveOnly}}"
+
+ initializeDefaultValue:
+ "{{#defaultValue}}{{>initializer}}{{/defaultValue}}\
+ {{^defaultValue}}{{>omittedValue}}{{/defaultValue}}"
+
+ # No inner indents in folded values!
+
+ joinedParamDecl: >-
+ {{>maybeCrefType}} {{paramName}}
+ {{^required?}} = {{>initializeDefaultValue}}{{/required?}}{{>cjoin}}
+ joinedParamDef: "{{>maybeCrefType}} {{paramName}}{{>cjoin}}"
+
+ passPathAndMaybeQuery: >-
+ QStringLiteral("{{basePathWithoutHost}}")
+ {{#pathParts}} % {{_}}{{/pathParts}}{{#queryParams?}},
+ queryTo{{camelCaseOperationId}}(
+ {{#queryParams}}{{paramName}}{{>cjoin}}{{/queryParams}}){{/queryParams?}}
+
+ nonInlineResponseSignature: |-
+ {{>docCommentShort}}
+ {{>maybeOmittableType}} {{paramName}}(){{^moveOnly}} const{{/moveOnly}}
# Doc-comment blocks. Comment indent is managed by clang-format
# (without clang-format there'd have to be a separate partial definition
- # for each indent...)
+ # for each indent...) but we take care of line breaks to maintain
+ # some sanity even before clang-format
- # For structures that are not supposed to have a summary (e.g., JSON schema)
+ # This is for structures that don't expect a summary (e.g., JSON schema)
docCommentShort: |-
{{#description}}
/// {{_}}{{/description}}
+ # For structures with the summary, a common partial for summary is here;
+ # the main part is different in different places
docCommentSummary: |-
{{#summary}} \brief {{summary}}
*{{/summary}}
templates:
data:
- .h: "{{>template.h.mustache}}"
- .cpp: "{{>template.cpp.mustache}}"
+ .h: "{{>data.h.mustache}}"
api:
- .h: "{{>template.h.mustache}}"
- .cpp: "{{>template.cpp.mustache}}"
+ .h: "{{>operation.h.mustache}}"
+ .cpp: "{{>operation.cpp.mustache}}"
#outFilesList: apifiles.txt
diff --git a/gtad/operation.cpp.mustache b/gtad/operation.cpp.mustache
new file mode 100644
index 00000000..3c3396e9
--- /dev/null
+++ b/gtad/operation.cpp.mustache
@@ -0,0 +1,58 @@
+{{>preamble}}
+#include "{{filenameBase}}.h"
+
+#include <QtCore/QStringBuilder>
+
+using namespace Quotient;
+{{#operations}}{{#operation}}
+ {{#queryParams?}}
+
+auto queryTo{{camelCaseOperationId}}(
+ {{#queryParams}}{{>joinedParamDef}}{{/queryParams}})
+{
+ BaseJob::Query _q;{{#queryParams}}
+ addParam<{{^required?}}IfNotEmpty{{/required?}}>(_q,
+ QStringLiteral("{{baseName}}"), {{paramName}});{{/queryParams}}
+ return _q;
+}
+ {{/queryParams?}}
+ {{^hasBody?}}
+
+QUrl {{camelCaseOperationId}}Job::makeRequestUrl(QUrl baseUrl{{#allParams?}},
+ {{#allParams}}{{>joinedParamDef}}{{/allParams}}{{/allParams?}})
+{
+ return BaseJob::makeRequestUrl(std::move(baseUrl), {{>passPathAndMaybeQuery}});
+} {{/hasBody?}}
+
+{{camelCaseOperationId}}Job::{{camelCaseOperationId}}Job(
+ {{#allParams}}{{>joinedParamDef}}{{/allParams}})
+ : BaseJob(HttpVerb::{{#_cap}}{{#_tolower}}{{httpMethod}}{{/_tolower}}{{/_cap}},
+ {{!object name}}QStringLiteral("{{camelCaseOperationId}}Job"),
+ {{>passPathAndMaybeQuery}}
+ {{#skipAuth}}{{#queryParams?}}, {}{{/queryParams?}}, false{{/skipAuth}} )
+{ {{#headerParams}}
+ setRequestHeader("{{baseName}}", {{paramName}}.toLatin1());
+ {{/headerParams}}{{#inlineBody}}{{^propertyMap}}{{^bodyParams?}}
+ setRequestData(Data({{#consumesNonJson?}}{{nameCamelCase}}{{/consumesNonJson?
+ }}{{^consumesNonJson?}}toJson({{nameCamelCase}}){{/consumesNonJson?}}));
+ {{/bodyParams?}}{{/propertyMap}}{{/inlineBody
+ }}{{^consumesNonJson?}}{{#bodyParams?}}
+ QJsonObject _data;
+ {{#propertyMap}}
+ fillJson(_data, {{nameCamelCase}});
+ {{/propertyMap}}{{#inlineBody}}
+ fillJson<{{>maybeOmittableType}}>(_data, {{paramName}});
+ {{/inlineBody}}{{#bodyParams}}
+ addParam<{{^required?}}IfNotEmpty{{/required?}}>(_data,
+ QStringLiteral("{{baseName}}"), {{paramName}});
+ {{/bodyParams}}
+ setRequestData(std::move(_data));
+ {{/bodyParams?}}{{/consumesNonJson?}}{{#producesNonJson?}}
+ setExpectedContentTypes({ {{#produces}}"{{_}}"{{>cjoin}}{{/produces}} });
+ {{/producesNonJson?}}{{^producesNonJson?
+ }}{{#responses}}{{#normalResponse?}}{{#properties}}{{#required?}}
+ addExpectedKey("{{baseName}}");
+ {{/required?}}{{/properties}}{{/normalResponse?}}{{/responses
+ }}{{/producesNonJson?}}
+}
+{{/operation}}{{/operations}}
diff --git a/gtad/operation.h.mustache b/gtad/operation.h.mustache
new file mode 100644
index 00000000..34c8a361
--- /dev/null
+++ b/gtad/operation.h.mustache
@@ -0,0 +1,128 @@
+{{>preamble}}
+#pragma once
+
+#include "jobs/basejob.h"
+{{#imports}}
+#include {{_}}{{/imports}}
+{{#operations.producesNonJson?}}
+#include <QtNetwork/QNetworkReply>{{/operations.producesNonJson?}}
+
+namespace Quotient {
+{{#operations.operation}}
+
+/*!{{>docCommentSummary}}{{#description}}
+ * {{_}}{{/description}}
+ */
+class {{camelCaseOperationId}}Job : public BaseJob {
+public:
+ {{#models}}
+ // Inner data structures
+ {{#model}}
+
+ {{>docCommentShort}}
+ struct {{name}}{{#parents?}} :
+ {{!Quotient:: is a workaround for cases when the same name is used for
+ the outer and the inner structure (unfortunately very easy
+ to hit if you don't give a title to the structure that has
+ $ref and other properties)}}
+ {{#parents}}Quotient::{{name}}{{>cjoin}}{{/parents}}{{/parents?}}
+ {
+ {{#vars}}
+ {{>docCommentShort}}
+ {{>maybeOmittableType}} {{nameCamelCase}};
+ {{/vars}}
+ {{#propertyMap}}
+ {{>docCommentShort}}
+ {{>maybeOmittableType}} {{nameCamelCase}};
+ {{/propertyMap}}
+ };
+ {{/model}}
+
+ // Construction/destruction
+
+ {{/models}}
+ {{#allParams?}}
+ /*!{{>docCommentSummary}}
+ {{#allParams}}
+ *
+ * \param {{nameCamelCase}}{{#description}}
+ * {{_}}{{/description}}
+ {{/allParams}}
+ */
+ {{/allParams?}}{{^allParams?}}
+ {{#summary}}
+ /// {{summary}}
+ {{/summary}}
+ {{/allParams?}}
+ explicit {{camelCaseOperationId}}Job({{#allParams}}{{>joinedParamDecl}}{{/allParams}});
+ {{^hasBody?}}
+
+ /*! \brief Construct a URL without creating a full-fledged job object
+ *
+ * This function can be used when a URL for {{camelCaseOperationId}}Job
+ * is necessary but the job itself isn't.
+ */
+ static QUrl makeRequestUrl(QUrl baseUrl{{#allParams?}},
+ {{#allParams}}{{>joinedParamDecl}}{{/allParams}}{{/allParams?}});
+ {{/hasBody?}}
+ {{#responses}}{{#normalResponse?}}{{#allProperties?}}
+
+ // Result properties
+ {{#headers}}
+
+ {{>nonInlineResponseSignature}}
+ {
+ return reply()->rawHeader("{{baseName}}");
+ }
+ {{/headers}}{{#inlineResponse}}
+
+ {{>docCommentShort}}
+ {{dataType.name}} {{paramName}}(){{^moveOnly}}{{^producesNonJson?}} const{{/producesNonJson?}}{{/moveOnly}}
+ {
+ return {{#producesNonJson?}}reply(){{/producesNonJson?}}
+ {{^producesNonJson?
+ }}fromJson<{{dataType.name}}>(jsonData()){{/producesNonJson?
+ }};
+ }
+ {{/inlineResponse}}{{#properties}}
+
+ {{!there's nothing in #properties if the response is inline}}
+ {{>nonInlineResponseSignature}}
+ {
+ return {{>takeOrLoad}}FromJson<{{>maybeOmittableType}}>("{{baseName}}"_ls);
+ }
+ {{/properties}}
+ {{/allProperties?}}{{/normalResponse?}}{{/responses}}
+};
+ {{#models.model}}
+
+template <> struct JsonObjectConverter<{{qualifiedName}}> {
+ {{#in?}}
+ static void dumpTo(QJsonObject& jo, const {{qualifiedName}}& pod)
+ { {{#propertyMap}}
+ fillJson(jo, pod.{{nameCamelCase}});
+ {{/propertyMap}}{{#parents}}
+ fillJson<{{name}}>(jo, pod);
+ {{/parents}}{{#vars}}
+ addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo,
+ QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}});
+ {{/vars}}
+ }
+ {{/in?}}
+ {{#out?}}
+ static void fillFrom({{>maybeCrefJsonObject}} jo, {{qualifiedName}}& result)
+ { {{#parents}}
+ fillFromJson<{{name}}{{!of the parent!}}>(jo, result);
+ {{/parents}}{{#vars}}
+ fromJson(jo.{{>takeOrValue}}("{{baseName}}"_ls),
+ result.{{nameCamelCase}});
+ {{/vars}}{{#propertyMap}}
+ fromJson(jo, result.{{nameCamelCase}});
+ {{/propertyMap}}
+ }
+ {{/out?}}
+};
+ {{/models.model}}
+{{/operations.operation}}
+
+} // namespace Quotient
diff --git a/gtad/template.cpp.mustache b/gtad/template.cpp.mustache
deleted file mode 100644
index b3bd4de9..00000000
--- a/gtad/template.cpp.mustache
+++ /dev/null
@@ -1,182 +0,0 @@
-{{>preamble}}
-#include "{{filenameBase}}.h"
-{{^models}}
-#include "converters.h"{{/models}}
-{{#operations}}
- {{#producesNonJson?}}
-#include <QtNetwork/QNetworkReply>
- {{/producesNonJson?}}
-#include <QtCore/QStringBuilder>
-{{/operations}}
-
-using namespace Quotient;
-
-{{#models.model}}
- {{#in?}}
-void JsonObjectConverter<{{qualifiedName}}>::dumpTo(
- QJsonObject& jo, const {{qualifiedName}}& pod)
-{ {{#propertyMap}}
- fillJson(jo, pod.{{nameCamelCase}});
- {{/propertyMap}}{{#parents}}
- fillJson<{{name}}>(jo, pod);
- {{/parents}}{{#vars}}
- addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo,
- QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}});
- {{/vars}}
-}
- {{/in?}}
-
- {{#out?}}
-void JsonObjectConverter<{{qualifiedName}}>::fillFrom(
- {{>maybeCrefJsonObject}} jo, {{qualifiedName}}& result)
-{ {{#parents}}
- fillFromJson<{{qualifiedName}}>(jo, result);
- {{/parents}}{{#vars}}
- fromJson(jo.{{>takeOrValue}}("{{baseName}}"_ls), result.{{nameCamelCase}});
- {{/vars}}{{#propertyMap}}
- fromJson(jo, result.{{nameCamelCase}});
- {{/propertyMap}}
-}
- {{/out?}}
-
-{{/models.model}}
-{{#operations}}
-
-static const auto basePath = QStringLiteral("{{basePathWithoutHost}}");
- {{#operation}}{{#models}}
-
-// Converters
-namespace Quotient {
- {{#model}}
-
-template <> struct JsonObjectConverter<{{qualifiedName}}> {
- {{#in?}}
- static void dumpTo(QJsonObject& jo, const {{qualifiedName}}& pod)
- { {{#propertyMap}}
- fillJson(jo, pod.{{nameCamelCase}});
- {{/propertyMap}}{{#parents}}
- fillJson<{{name}}>(jo, pod);
- {{/parents}}{{#vars}}
- addParam<{{^required?}}IfNotEmpty{{/required?}}>(jo,
- QStringLiteral("{{baseName}}"), pod.{{nameCamelCase}});
- {{/vars}}
- }
- {{/in?}}
- {{#out?}}
- static void fillFrom({{>maybeCrefJsonObject}} jo, {{qualifiedName}}& result)
- { {{#parents}}
- fillFromJson<{{qualifiedName}}{{!of the parent!}}>(jo, result);
- {{/parents}}{{#vars}}
- fromJson(jo.{{>takeOrValue}}("{{baseName}}"_ls),
- result.{{nameCamelCase}});
- {{/vars}}{{#propertyMap}}
- fromJson(jo, result.{{nameCamelCase}});
- {{/propertyMap}}
- }
- {{/out?}}
-};
- {{/model}}
-
-} // namespace Quotient
- {{/models}}
- {{#responses}}{{#normalResponse?}}{{#allProperties?}}
-
-class {{camelCaseOperationId}}Job::Private
-{
- public:{{#allProperties}}
- {{>maybeOmittableType}} {{paramName}};{{/allProperties}}
-};
- {{/allProperties?}}{{/normalResponse?}}{{/responses}}
- {{#queryParams?}}
-
-BaseJob::Query queryTo{{camelCaseOperationId}}(
- {{#queryParams}}{{>joinedParamDef}}{{/queryParams}})
-{
- BaseJob::Query _q;{{#queryParams}}
- addParam<{{^required?}}IfNotEmpty{{/required?}}>(_q,
- QStringLiteral("{{baseName}}"), {{paramName}});{{/queryParams}}
- return _q;
-}
- {{/queryParams?}}
- {{^bodyParams}}
-
-QUrl {{camelCaseOperationId}}Job::makeRequestUrl(QUrl baseUrl{{#allParams?}},
- {{#allParams}}{{>joinedParamDef}}{{/allParams}}{{/allParams?}})
-{
- return BaseJob::makeRequestUrl(std::move(baseUrl),
- basePath{{#pathParts}} % {{_}}{{/pathParts}}{{#queryParams?}},
- queryTo{{camelCaseOperationId}}({{>passQueryParams}}){{/queryParams?}});
-} {{/bodyParams}}
-
-{{camelCaseOperationId}}Job::{{camelCaseOperationId}}Job(
- {{#allParams}}{{>joinedParamDef}}{{/allParams}})
- : BaseJob(HttpVerb::{{#_cap}}{{#_tolower}}{{httpMethod}}{{/_tolower}}{{/_cap}},
- QStringLiteral("{{camelCaseOperationId}}Job"), {{!object name}}
- basePath{{#pathParts}} % {{_}}{{/pathParts}} {{!API endpoint}}
- {{#queryParams?
- }} , queryTo{{camelCaseOperationId}}({{>passQueryParams}})
- {{/queryParams?
- }}{{#skipAuth}}{{#queryParams?}}, {}{{/queryParams?}}, false{{/skipAuth}} )
- {{#responses}}{{#normalResponse?}}{{#allProperties?
- }}, d(new Private){{/allProperties?}}{{/normalResponse?}}{{/responses}}
-{ {{#headerParams}}
- setRequestHeader("{{baseName}}", {{paramName}}.toLatin1());
- {{/headerParams}}{{#bodyParams?}}
- {{#inlineBody}}
- setRequestData(Data({{!avoid extra linebreaks}}{{
- #consumesNonJson?}}{{nameCamelCase}}{{/consumesNonJson?}}{{
- ^consumesNonJson?}}toJson({{nameCamelCase}}){{/consumesNonJson?
- }}));
- {{/inlineBody}}{{^inlineBody}}
- QJsonObject _data;
- {{#bodyParams}}
- addParam<{{^required?}}IfNotEmpty{{/required?}}>(_data,
- QStringLiteral("{{baseName}}"), {{paramName}});
- {{/bodyParams}}
- setRequestData(_data);
- {{/inlineBody}}
- {{/bodyParams?}}{{#producesNonJson?}}
- setExpectedContentTypes({ {{#produces}}"{{_}}"{{>cjoin}}{{/produces}} });
- {{/producesNonJson?}}
-}
- {{#responses}}{{#normalResponse?}}{{#allProperties?}}
-
-{{camelCaseOperationId}}Job::~{{camelCaseOperationId}}Job() = default;
- {{#allProperties}}
-
-{{>qualifiedMaybeCrefType}}
- {{camelCaseOperationId}}Job::{{paramName}}(){{^moveOnly}} const{{/moveOnly}}
-{
- return {{#moveOnly}}std::move({{/moveOnly}}d->{{paramName}}{{#moveOnly}}){{/moveOnly}};
-}
- {{/allProperties}}
-
- {{#producesNonJson?}}
-BaseJob::Status {{camelCaseOperationId}}Job::parseReply(QNetworkReply* reply)
-{
- {{! We don't check for required headers yet }}
- {{#headers}}d->{{paramName}} = reply->rawHeader("{{baseName}}");
- {{/headers}}{{#properties}}d->{{paramName}} = reply;{{/properties}}
- return Success;
-}
- {{/producesNonJson?}}{{^producesNonJson?}}
-BaseJob::Status {{camelCaseOperationId}}Job::parseJson(const QJsonDocument& data)
-{
- {{#inlineResponse}}
- fromJson(data, d->{{paramName}});
- {{/inlineResponse}}{{^inlineResponse}}
- auto json = data.object();
- {{#properties}}{{#required?}}
- if (!json.contains("{{baseName}}"_ls))
- return { IncorrectResponse,
- "The key '{{baseName}}' not found in the response" };
- {{/required?}}
- fromJson(json.value("{{baseName}}"_ls), d->{{paramName}});
- {{/properties}}
- {{/inlineResponse}}
-
- return Success;
-}
- {{/producesNonJson?}}
- {{/allProperties?}}{{/normalResponse?}}{{/responses}}
-{{/operation}}{{/operations}}
diff --git a/gtad/template.h.mustache b/gtad/template.h.mustache
deleted file mode 100644
index 404aafe8..00000000
--- a/gtad/template.h.mustache
+++ /dev/null
@@ -1,119 +0,0 @@
-{{>preamble}}
-#pragma once
-
-{{#operations}}
-#include "jobs/basejob.h"{{/operations}}
-{{#models}}
-#include "converters.h"{{/models}}
-{{#imports}}
-#include {{_}}{{/imports}}
-
-namespace Quotient {
-{{#models}}
-
-// Data structures
-
- {{#model}}
-{{>docCommentShort}}
-struct {{name}}{{#parents?}} : {{#parents}}{{name}}{{>cjoin}}{{/parents}}{{/parents?}}
-{ {{#vars}}
-
- {{>docCommentShort}}
- {{>maybeOmittableType}} {{nameCamelCase}};
- {{/vars}}{{#propertyMap}}
-
- {{>docCommentShort}}
- {{>maybeOmittableType}} {{nameCamelCase}};
- {{/propertyMap}}
-};
-
-template <> struct JsonObjectConverter<{{name}}>
-{
- {{#in?}}
- static void dumpTo(QJsonObject& jo, const {{name}}& pod);
- {{/in?}}
- {{#out?}}
- static void fillFrom({{>maybeCrefJsonObject}} jo, {{name}}& pod);
- {{/out?}}
-};
- {{/model}}
-{{/models}}
-{{#operations}}
-
-// Operations
- {{#operation}}
-
-/*!{{>docCommentSummary}}{{#description}}
- * {{_}}{{/description}}
- */
-class {{camelCaseOperationId}}Job : public BaseJob {
-public: {{#models}}
- // Inner data structures
- {{#model}}
-
- {{>docCommentShort}}
- struct {{name}}{{#parents?}} :
- {{#parents}}{{name}}{{>cjoin}}{{/parents}}{{/parents?}}
- {
- {{#vars}}
- {{>docCommentShort}}
- {{>maybeOmittableType}} {{nameCamelCase}};
- {{/vars}}
- {{#propertyMap}}
- {{>docCommentShort}}
- {{>maybeOmittableType}} {{nameCamelCase}};
- {{/propertyMap}}
- };
- {{/model}}
-
- // Construction/destruction
-
- {{/models}}
- {{^allParams?}}
- {{#summary}}
- /// {{summary}}
- {{/summary}}
- {{/allParams?}}{{#allParams?}}
- /*!{{>docCommentSummary}}
- {{#allParams}}
- * \param {{nameCamelCase}}{{#description}}
- * {{_}}{{/description}}
- {{/allParams}}
- */
- {{/allParams?}}
- explicit {{camelCaseOperationId}}Job({{#allParams}}{{>joinedParamDecl}}{{/allParams}});
- {{^bodyParams}}
-
- /*! \brief Construct a URL without creating a full-fledged job object
- *
- * This function can be used when a URL for {{camelCaseOperationId}}Job
- * is necessary but the job itself isn't.
- */
- static QUrl makeRequestUrl(QUrl baseUrl{{#allParams?}},
- {{#allParams}}{{>joinedParamDecl}}{{/allParams}}{{/allParams?}});
- {{/bodyParams}}
- {{#responses}}{{#normalResponse?}}{{#allProperties?}}
- ~{{camelCaseOperationId}}Job() override;
-
- // Result properties
- {{#allProperties}}
-
- {{>docCommentShort}}
- {{>maybeCrefType}} {{paramName}}(){{^moveOnly}} const{{/moveOnly}};
- {{/allProperties}}
-
-protected: {{#producesNonJson?}}
- Status parseReply(QNetworkReply* reply) override;
- {{/producesNonJson?}}{{^producesNonJson?}}
- Status parseJson(const QJsonDocument& data) override;
- {{/producesNonJson?}}
-
-private:
- class Private;
- QScopedPointer<Private> d;
- {{/allProperties?}}{{/normalResponse?}}{{/responses}}
-};
- {{/operation}}
-{{/operations}}
-
-} // namespace Quotient
diff --git a/libquotient.pri b/libquotient.pri
index df58d35b..4fee6723 100644
--- a/libquotient.pri
+++ b/libquotient.pri
@@ -112,10 +112,6 @@ SOURCES += \
$$SRCPATH/jobs/mediathumbnailjob.cpp \
$$SRCPATH/jobs/downloadfilejob.cpp \
$$files($$SRCPATH/csapi/*.cpp, false) \
- $$files($$SRCPATH/csapi/definitions/*.cpp, false) \
- $$files($$SRCPATH/csapi/definitions/wellknown/*.cpp, false) \
- $$files($$SRCPATH/application-service/definitions/*.cpp, false) \
- $$files($$SRCPATH/identity/definitions/*.cpp, false) \
$$SRCPATH/logging.cpp \
$$SRCPATH/converters.cpp \
$$SRCPATH/settings.cpp \