77 const QString name = method.name;
78 const QList<Variable> ¶meterList = method.parameterList;
80 QStringList headerParamList;
81 QStringList cppParamList;
82 for (
const Variable &variable : parameterList) {
83 const QString commonPart = variable.cppType + u" " + variable.name;
84 cppParamList << commonPart;
85 headerParamList << commonPart;
86 if (!variable.defaultValue.isEmpty())
87 headerParamList.back() += u" = " + variable.defaultValue;
90 const QString headerSignature = name + u"(" + headerParamList.join(u", "_s) + u")"
91 + prependSpace(method.modifiers.join(u" "));
92 const QString cppSignature = name + u"(" + cppParamList.join(u", "_s) + u")"
93 + prependSpace(method.modifiers.join(u" "));
94 return { headerSignature, cppSignature };
102void CodeWriter::writeGlobalHeader(OutputWrapper &code,
const QString &sourcePath,
103 const QString &hPath,
const QString &cppPath,
104 const QString &outNamespace,
105 const QSet<QString> &requiredCppIncludes)
108 const QString preamble = u"// This code is auto-generated by the qmltc tool from the file '"
109 + sourcePath + u"'\n// WARNING! All changes made in this file will be lost!\n";
110 code.rawAppendToHeader(preamble);
111 code.rawAppendToCpp(preamble);
112 code.rawAppendToHeader(
113 u"// NOTE: This generated API is to be considered implementation detail.");
114 code.rawAppendToHeader(
115 u"// It may change from version to version and should not be relied upon.");
117 const QString headerMacro = urlToMacro(sourcePath);
118 code.rawAppendToHeader(u"#ifndef %1_H"_s.arg(headerMacro));
119 code.rawAppendToHeader(u"#define %1_H"_s.arg(headerMacro));
121 code.rawAppendToHeader(u"#include <QtCore/qproperty.h>");
122 code.rawAppendToHeader(u"#include <QtCore/qobject.h>");
123 code.rawAppendToHeader(u"#include <QtCore/qcoreapplication.h>");
124 code.rawAppendToHeader(u"#include <QtCore/qxpfunctional.h>");
125 code.rawAppendToHeader(u"#include <QtQml/qqmlengine.h>");
126 code.rawAppendToHeader(u"#include <QtCore/qurl.h>");
127 code.rawAppendToHeader(u"#include <QtQml/qqml.h>");
129 code.rawAppendToHeader(u"#include <private/qqmlengine_p.h>");
130 code.rawAppendToHeader(u"#include <private/qqmltcobjectcreationhelper_p.h>");
132 code.rawAppendToHeader(u"#include <QtQml/qqmllist.h>");
135 code.rawAppendToHeader(u"// BEGIN(custom_cpp_includes)");
136 for (
const auto &requiredInclude : requiredCppIncludes)
137 code.rawAppendToHeader(u"#include \"" + requiredInclude + u"\"");
138 code.rawAppendToHeader(u"// END(custom_cpp_includes)");
140 code.rawAppendToCpp(u"#include \"" + hPath + u"\"");
141 code.rawAppendToCpp(u"// qmltc support library:");
142 code.rawAppendToCpp(u"#include <private/qqmlcppbinding_p.h>");
143 code.rawAppendToCpp(u"#include <private/qqmlcpponassignment_p.h>");
144 code.rawAppendToHeader(u"#include <private/qqmlcpptypehelpers_p.h> ");
146 code.rawAppendToCpp(u"#include <private/qqmlobjectcreator_p.h>");
147 code.rawAppendToCpp(u"#include <private/qqmlcomponent_p.h>");
149 code.rawAppendToCpp(u"");
150 code.rawAppendToCpp(u"#include <private/qobject_p.h>");
151 code.rawAppendToCpp(u"#include <private/qqmlobjectcreator_p.h>");
152 code.rawAppendToCpp(u"#include <QtQml/qqmlprivate.h>");
154 code.rawAppendToCpp(u"");
155 code.rawAppendToCpp(u"QT_USE_NAMESPACE // avoid issues with QT_NAMESPACE");
157 code.rawAppendToHeader(u"");
159 const QStringList namespaces = outNamespace.split(u"::"_s);
161 for (
const QString ¤tNamespace : namespaces) {
162 code.rawAppendToHeader(u"namespace %1 {"_s.arg(currentNamespace));
163 code.rawAppendToCpp(u"namespace %1 {"_s.arg(currentNamespace));
167void CodeWriter::write(OutputWrapper &code,
const PropertyInitializer &propertyInitializer,
168 const Type &wrappedType)
170 code.rawAppendToHeader(u"class " + propertyInitializer.name + u" {");
174 [[maybe_unused]] OutputWrapper::HeaderIndentationScope headerIndent(&code);
176 code.rawAppendToHeader(u"friend class " + wrappedType.cppType + u";");
179 code.rawAppendToHeader(u"public:"_s);
181 [[maybe_unused]] OutputWrapper::MemberNameScope typeScope(&code, propertyInitializer.name);
183 [[maybe_unused]] OutputWrapper::HeaderIndentationScope headerIndent(&code);
185 write(code, propertyInitializer.constructor);
186 code.rawAppendToHeader(u"");
188 for (
const auto &propertySetter : propertyInitializer.propertySetters) {
189 write(code, propertySetter);
193 code.rawAppendToHeader(u"");
194 code.rawAppendToHeader(u"private:"_s);
197 [[maybe_unused]] OutputWrapper::HeaderIndentationScope headerIndent(&code);
199 write(code, propertyInitializer.component);
200 write(code, propertyInitializer.initializedCache);
204 code.rawAppendToHeader(u"};"_s);
205 code.rawAppendToHeader(u"");
262void CodeWriter::write(OutputWrapper &code,
const Program &program)
264 writeGlobalHeader(code, program.url, program.hPath, program.cppPath, program.outNamespace,
268 writeUrl(code, program.urlMethod);
271 for (
const Type &type : std::as_const(program.compiledTypes))
272 code.rawAppendToHeader(u"class " + type.cppType + u";");
274 for (
const Type &type : std::as_const(program.compiledTypes))
275 write(code, type, program.exportMacro);
280 for (
const Type &type : std::as_const(program.compiledTypes)) {
283 code.rawAppendToHeader(u"");
284 code.rawAppendToHeader(u"constexpr %1 %2::%3()"_s.arg(type.typeCount->returnType,
285 type.cppType, type.typeCount->name));
286 code.rawAppendToHeader(u"{");
287 for (
const QString &line : std::as_const(type.typeCount->body))
288 code.rawAppendToHeader(line, 1);
289 code.rawAppendToHeader(u"}");
292 writeGlobalFooter(code, program.url, program.outNamespace);
294 writeToFile(program.hPath, code.code().header.toUtf8());
295 writeToFile(program.cppPath, code.code().cpp.toUtf8());
316void CodeWriter::write(OutputWrapper &code,
const Type &type,
const QString &exportMacro)
318 const auto constructClassString = [&]() {
319 QString str = u"class "_s;
320 if (!exportMacro.isEmpty())
321 str.append(exportMacro).append(u" "_s);
322 str.append(type.cppType);
323 QStringList nonEmptyBaseClasses;
324 nonEmptyBaseClasses.reserve(type.baseClasses.size());
325 std::copy_if(type.baseClasses.cbegin(), type.baseClasses.cend(),
326 std::back_inserter(nonEmptyBaseClasses),
327 [](
const QString &entry) {
return !entry.isEmpty(); });
328 if (!nonEmptyBaseClasses.isEmpty())
329 str += u" : public " + nonEmptyBaseClasses.join(u", public "_s);
333 code.rawAppendToHeader(u"");
334 code.rawAppendToCpp(u"");
336 code.rawAppendToHeader(constructClassString());
337 code.rawAppendToHeader(u"{");
338 for (
const QString &mocLine : std::as_const(type.mocCode))
339 code.rawAppendToHeader(mocLine, 1);
341 OutputWrapper::MemberNameScope typeScope(&code, type.cppType);
344 OutputWrapper::HeaderIndentationScope headerIndent(&code);
345 Q_UNUSED(headerIndent);
351 code.rawAppendToHeader(u"/* ----------------- */");
352 code.rawAppendToHeader(u"/* External C++ API */");
353 code.rawAppendToHeader(u"public:", -1);
355 if (!type.propertyInitializer.name.isEmpty())
356 write(code, type.propertyInitializer, type);
358 if (type.requiredPropertiesBundle)
359 write(code, *type.requiredPropertiesBundle);
363 if (!type.ignoreInit && type.externalCtor.access == QQmlJSMetaMethod::Public) {
366 CodeWriter::write(code, type.externalCtor);
367 if (type.staticCreate)
368 CodeWriter::write(code, *type.staticCreate);
373 CodeWriter::write(code, *type.dtor);
376 for (
const auto &enumeration : std::as_const(type.enums))
377 CodeWriter::write(code, enumeration);
380 const auto isUserVisibleFunction = [](
const Method &function) {
381 return function.userVisible;
383 dumpFunctions(code, type.functions, isUserVisibleFunction);
385 code.rawAppendToHeader(u"/* ----------------- */");
386 code.rawAppendToHeader(u"");
387 code.rawAppendToHeader(u"/* Internal functionality (do NOT use it!) */");
392 if (type.ignoreInit) {
393 Q_ASSERT(type.baselineCtor.access == QQmlJSMetaMethod::Public);
394 code.rawAppendToHeader(u"public:", -1);
395 CodeWriter::write(code, type.baselineCtor);
397 code.rawAppendToHeader(u"protected:", -1);
398 if (type.externalCtor.access != QQmlJSMetaMethod::Public) {
399 Q_ASSERT(type.externalCtor.access == QQmlJSMetaMethod::Protected);
400 CodeWriter::write(code, type.externalCtor);
402 CodeWriter::write(code, type.baselineCtor);
403 CodeWriter::write(code, type.init);
404 CodeWriter::write(code, type.endInit);
405 CodeWriter::write(code, type.setComplexBindings);
406 CodeWriter::write(code, type.beginClass);
407 CodeWriter::write(code, type.completeComponent);
408 CodeWriter::write(code, type.finalizeComponent);
409 CodeWriter::write(code, type.handleOnCompleted);
413 for (
const auto &child : std::as_const(type.children))
414 CodeWriter::write(code, child, exportMacro);
417 dumpFunctions(code, type.functions,
418 [&](
const auto &m) {
return !isUserVisibleFunction(m); });
421 if (!type.variables.isEmpty() || !type.properties.isEmpty()) {
422 code.rawAppendToHeader(u"");
423 code.rawAppendToHeader(u"protected:", -1);
425 for (
const auto &property : std::as_const(type.properties))
426 write(code, property);
427 for (
const auto &variable : std::as_const(type.variables))
428 write(code, variable);
431 code.rawAppendToHeader(u"private:", -1);
432 for (
const QString &otherLine : std::as_const(type.otherCode))
433 code.rawAppendToHeader(otherLine, 1);
435 if (type.typeCount) {
437 code.rawAppendToHeader(u"");
438 code.rawAppendToHeader(u"protected:");
439 code.rawAppendToHeader(u"constexpr static %1 %2();"_s.arg(type.typeCount->returnType,
440 type.typeCount->name),
444 code.rawAppendToHeader(u"};");
463void CodeWriter::write(OutputWrapper &code,
const Method &method)
465 const auto [hSignature, cppSignature] = functionSignatures(method);
467 code.rawAppendToHeader((method.type == QQmlJSMetaMethodType::StaticMethod
468 ? u"static " + functionReturnType(method)
469 : functionReturnType(method))
470 + u" " + hSignature + u";");
473 const auto methodType = method.type;
474 if (methodType != QQmlJSMetaMethodType::Signal) {
475 code.rawAppendToCpp(u""_s);
476 if (method.comments.size() > 0) {
477 code.rawAppendToCpp(u"/*! \\internal"_s);
478 for (
const auto &comment : method.comments)
479 code.rawAppendToCpp(comment, 1);
480 code.rawAppendToCpp(u"*/"_s);
482 code.rawAppendToCpp(method.returnType);
483 code.rawAppendSignatureToCpp(cppSignature);
484 code.rawAppendToCpp(u"{");
486 OutputWrapper::CppIndentationScope cppIndent(&code);
488 for (
const QString &line : std::as_const(method.body))
489 code.rawAppendToCpp(line);
491 code.rawAppendToCpp(u"}");