From 983432effdae888a372d814ff9516abbcb7a3c29 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 3 Jan 2020 15:03:39 +0100 Subject: Introduce Q_MOC_INCLUDE A new macro that can be added in the header file parsed by moc to tell moc to include that file in the generated file Change-Id: I03ad702c3fcd8380371015f226ee4b7456daf132 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobject.cpp | 17 ++++++ src/corelib/kernel/qtmetamacros.h | 1 + src/tools/moc/keywords.cpp | 25 ++++++--- src/tools/moc/moc.cpp | 21 ++++++++ src/tools/moc/moc.h | 1 + src/tools/moc/token.h | 1 + src/tools/moc/util/generate_keywords.cpp | 1 + tests/auto/tools/moc/allmocs_baseline_in.json | 59 +++++++++++++++++++++ tests/auto/tools/moc/fwdclass1.h | 38 ++++++++++++++ tests/auto/tools/moc/fwdclass2.h | 38 ++++++++++++++ tests/auto/tools/moc/fwdclass3.h | 38 ++++++++++++++ tests/auto/tools/moc/moc.pro | 3 +- tests/auto/tools/moc/moc_include.h | 74 +++++++++++++++++++++++++++ tests/auto/tools/moc/tst_moc.cpp | 33 ++++++++++-- 14 files changed, 339 insertions(+), 11 deletions(-) create mode 100644 tests/auto/tools/moc/fwdclass1.h create mode 100644 tests/auto/tools/moc/fwdclass2.h create mode 100644 tests/auto/tools/moc/fwdclass3.h create mode 100644 tests/auto/tools/moc/moc_include.h diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 133ccc88d9..c72383ff4a 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4542,6 +4542,23 @@ QDebug operator<<(QDebug dbg, const QObject *o) \sa Q_NAMESPACE, {Creating Shared Libraries} */ +/*! + \macro Q_MOC_INCLUDE + \relates QObject + \since 6.0 + + The Q_MOC_INCLUDE macro can be used within or outside a class, and tell the + \l{moc}{Meta Object Compiler} to add an include. + + \code + // Put this in your code and the generated code will include this header. + Q_MOC_INCLUDE("myheader.h") + \endcode + + This is useful if the types you use as properties or signal/slots arguments + are forward declared. +*/ + /*! \macro Q_SIGNALS \relates QObject diff --git a/src/corelib/kernel/qtmetamacros.h b/src/corelib/kernel/qtmetamacros.h index 19b6bfa358..1d095c0d7c 100644 --- a/src/corelib/kernel/qtmetamacros.h +++ b/src/corelib/kernel/qtmetamacros.h @@ -112,6 +112,7 @@ QT_BEGIN_NAMESPACE #define Q_INVOKABLE QT_ANNOTATE_FUNCTION(qt_invokable) #define Q_SIGNAL QT_ANNOTATE_FUNCTION(qt_signal) #define Q_SLOT QT_ANNOTATE_FUNCTION(qt_slot) +#define Q_MOC_INCLUDE(...) QT_ANNOTATE_CLASS(qt_moc_include, __VA_ARGS__) #endif // QT_NO_META_MACROS #ifndef QT_NO_TRANSLATION diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp index 7da8d94efc..cc7d747f5b 100644 --- a/src/tools/moc/keywords.cpp +++ b/src/tools/moc/keywords.cpp @@ -30,12 +30,12 @@ // DO NOT EDIT. static const short keyword_trans[][128] = { - {0,0,0,0,0,0,0,0,0,568,565,0,0,0,0,0, + {0,0,0,0,0,0,0,0,0,579,576,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 568,252,566,569,8,38,239,567,25,26,236,234,30,235,27,237, + 579,252,577,580,8,38,239,578,25,26,236,234,30,235,27,237, 22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43, 0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,21,8,8,8,8,8,8,8,8,8,31,571,32,238,8, + 8,21,8,8,8,8,8,8,8,8,8,31,582,32,238,8, 0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13, 14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -177,7 +177,7 @@ static const short keyword_trans[][128] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0, - 574,574,574,574,574,574,574,574,574,574,0,0,0,0,0,0, + 585,585,585,585,585,585,585,585,585,585,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -336,7 +336,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,573,0,0,0,0,572, + 0,0,0,0,0,0,0,0,0,0,584,0,0,0,0,583, 0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -378,7 +378,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,475,424,408,416,380,0,484,0,0,0,0,364,358, + 0,0,0,475,424,408,416,380,0,484,0,0,0,565,364,358, 386,0,557,472,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, @@ -1021,11 +1021,22 @@ static const struct {CHARACTER, 0, 79, 563, CHARACTER}, {CHARACTER, 0, 78, 564, CHARACTER}, {Q_REVISION_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 79, 566, CHARACTER}, + {CHARACTER, 0, 67, 567, CHARACTER}, + {CHARACTER, 0, 95, 568, CHARACTER}, + {CHARACTER, 0, 73, 569, CHARACTER}, + {CHARACTER, 0, 78, 570, CHARACTER}, + {CHARACTER, 0, 67, 571, CHARACTER}, + {CHARACTER, 0, 76, 572, CHARACTER}, + {CHARACTER, 0, 85, 573, CHARACTER}, + {CHARACTER, 0, 68, 574, CHARACTER}, + {CHARACTER, 0, 69, 575, CHARACTER}, + {Q_MOC_INCLUDE_TOKEN, 0, 0, 0, CHARACTER}, {NEWLINE, 0, 0, 0, NOTOKEN}, {QUOTE, 0, 0, 0, NOTOKEN}, {SINGLEQUOTE, 0, 0, 0, NOTOKEN}, {WHITESPACE, 0, 0, 0, NOTOKEN}, - {HASH, 0, 35, 570, HASH}, + {HASH, 0, 35, 581, HASH}, {PP_HASHHASH, 0, 0, 0, NOTOKEN}, {BACKSLASH, 0, 0, 0, NOTOKEN}, {CPP_COMMENT, 0, 0, 0, NOTOKEN}, diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 7b132493f8..2fb8c8dee3 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -653,6 +653,11 @@ void Moc::parse() case Q_CLASSINFO_TOKEN: parseClassInfo(&def); break; + case Q_MOC_INCLUDE_TOKEN: + // skip it, the namespace is parsed twice + next(LPAREN); + lexemUntil(RPAREN); + break; case ENUM: { EnumDef enumDef; if (parseEnum(&enumDef)) @@ -696,6 +701,9 @@ void Moc::parse() case Q_DECLARE_METATYPE_TOKEN: parseDeclareMetatype(); break; + case Q_MOC_INCLUDE_TOKEN: + parseMocInclude(); + break; case USING: if (test(NAMESPACE)) { while (test(SCOPE) || test(IDENTIFIER)) @@ -828,6 +836,9 @@ void Moc::parse() case Q_CLASSINFO_TOKEN: parseClassInfo(&def); break; + case Q_MOC_INCLUDE_TOKEN: + parseMocInclude(); + break; case Q_INTERFACES_TOKEN: parseInterfaces(&def); break; @@ -1562,6 +1573,16 @@ void Moc::parseDeclareMetatype() metaTypes.append(typeName); } +void Moc::parseMocInclude() +{ + next(LPAREN); + QByteArray include = lexemUntil(RPAREN); + // remove parentheses + include.remove(0, 1); + include.chop(1); + includeFiles.append(include); +} + void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access) { next(LPAREN); diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 1d70fa154b..91a03a767f 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -256,6 +256,7 @@ public: void parseInterfaces(ClassDef *def); void parseDeclareInterface(); void parseDeclareMetatype(); + void parseMocInclude(); void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access); void parsePrivateProperty(ClassDef *def); diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h index 0cc163f9e4..c11ec6a38c 100644 --- a/src/tools/moc/token.h +++ b/src/tools/moc/token.h @@ -179,6 +179,7 @@ QT_BEGIN_NAMESPACE F(Q_SCRIPTABLE_TOKEN) \ F(Q_PRIVATE_PROPERTY_TOKEN) \ F(Q_REVISION_TOKEN) \ + F(Q_MOC_INCLUDE_TOKEN) \ F(SPECIAL_TREATMENT_MARK) \ F(MOC_INCLUDE_BEGIN) \ F(MOC_INCLUDE_END) \ diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp index 9248e9e2e7..c2cfe37fab 100644 --- a/src/tools/moc/util/generate_keywords.cpp +++ b/src/tools/moc/util/generate_keywords.cpp @@ -243,6 +243,7 @@ static const Keyword keywords[] = { { "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" }, { "Q_PRIVATE_PROPERTY", "Q_PRIVATE_PROPERTY_TOKEN" }, { "Q_REVISION", "Q_REVISION_TOKEN" }, + { "Q_MOC_INCLUDE", "Q_MOC_INCLUDE_TOKEN" }, { "\n", "NEWLINE" }, { "\"", "QUOTE" }, { "\'", "SINGLEQUOTE" }, diff --git a/tests/auto/tools/moc/allmocs_baseline_in.json b/tests/auto/tools/moc/allmocs_baseline_in.json index c8abba6a8f..2a70a52587 100644 --- a/tests/auto/tools/moc/allmocs_baseline_in.json +++ b/tests/auto/tools/moc/allmocs_baseline_in.json @@ -1012,6 +1012,65 @@ "inputFile": "grand-parent-gadget-class.h", "outputRevision": 67 }, + { + "classes": [ + { + "className": "TestFwdProperties", + "properties": [ + { + "constant": false, + "designable": true, + "final": false, + "name": "prop1", + "read": "getProp1", + "scriptable": true, + "stored": true, + "type": "FwdClass1", + "user": false, + "write": "setProp1" + }, + { + "constant": false, + "designable": true, + "final": false, + "name": "prop2", + "read": "getProp2", + "scriptable": true, + "stored": true, + "type": "FwdClass2", + "user": false, + "write": "setProp2" + }, + { + "constant": false, + "designable": true, + "final": false, + "name": "prop3", + "read": "getProp3", + "scriptable": true, + "stored": true, + "type": "FwdClass3", + "user": false, + "write": "setProp3" + } + ], + "qualifiedClassName": "TestFwdProperties", + "superClasses": [ + { + "access": "public", + "name": "QObject" + } + ] + }, + { + "className": "SomeRandomNamespace", + "gadget": true, + "qualifiedClassName": "SomeRandomNamespace" + } + ], + "inputFile": "moc_include.h", + "outputRevision": 67 + }, { "classes": [ { diff --git a/tests/auto/tools/moc/fwdclass1.h b/tests/auto/tools/moc/fwdclass1.h new file mode 100644 index 0000000000..a8457cca77 --- /dev/null +++ b/tests/auto/tools/moc/fwdclass1.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Olivier Goffart +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifdef FWDCLASS1_H +#error "This file can only be included once" +#endif +#define FWDCLASS1_H + +class FwdClass1 +{ +public: + int x; +}; diff --git a/tests/auto/tools/moc/fwdclass2.h b/tests/auto/tools/moc/fwdclass2.h new file mode 100644 index 0000000000..650da18116 --- /dev/null +++ b/tests/auto/tools/moc/fwdclass2.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Olivier Goffart +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifdef FWDCLASS2_H +#error "This file can only be included once" +#endif +#define FWDCLASS2_H + +class FwdClass2 +{ +public: + int x; +}; diff --git a/tests/auto/tools/moc/fwdclass3.h b/tests/auto/tools/moc/fwdclass3.h new file mode 100644 index 0000000000..080ac0340d --- /dev/null +++ b/tests/auto/tools/moc/fwdclass3.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Olivier Goffart +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifdef FWDCLASS3_H +#error "This file can only be included once" +#endif +#define FWDCLASS3_H + +class FwdClass3 +{ +public: + int x; +}; diff --git a/tests/auto/tools/moc/moc.pro b/tests/auto/tools/moc/moc.pro index 93ca330126..094c76227b 100644 --- a/tests/auto/tools/moc/moc.pro +++ b/tests/auto/tools/moc/moc.pro @@ -30,7 +30,8 @@ HEADERS += using-namespaces.h no-keywords.h task87883.h c-comments.h backslash-n related-metaobjects-in-gadget.h \ related-metaobjects-name-conflict.h \ namespace.h cxx17-namespaces.h \ - cxx-attributes.h + cxx-attributes.h \ + moc_include.h # No platform specifics in the JSON files, so that we can compare them JSON_HEADERS = $$HEADERS diff --git a/tests/auto/tools/moc/moc_include.h b/tests/auto/tools/moc/moc_include.h new file mode 100644 index 0000000000..49b484a0c9 --- /dev/null +++ b/tests/auto/tools/moc/moc_include.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Olivier Goffart +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MOC_INCLUDE_H +#define MOC_INCLUDE_H + +#include + +class FwdClass1; +class FwdClass2; +class FwdClass3; + +Q_MOC_INCLUDE(fwdclass3.h) + +namespace SomeRandomNamespace { +Q_MOC_INCLUDE("fwdclass1.h") +Q_NAMESPACE +} + +class TestFwdProperties : public QObject +{ + Q_OBJECT + Q_PROPERTY(FwdClass1 prop1 WRITE setProp1 READ getProp1) + Q_PROPERTY(FwdClass2 prop2 WRITE setProp2 READ getProp2) + Q_PROPERTY(FwdClass3 prop3 WRITE setProp3 READ getProp3) +public: + ~TestFwdProperties(); + + void setProp1(const FwdClass1 &val); + void setProp2(const FwdClass2 &val); + void setProp3(const FwdClass3 &val); + const FwdClass1 &getProp1() { return *prop1; } + const FwdClass2 &getProp2() { return *prop2; } + const FwdClass3 &getProp3() { return *prop3; } + + QScopedPointer prop1; + QScopedPointer prop2; + QScopedPointer prop3; + + Q_MOC_INCLUDE( + \ + "fwdclass2.h" + ) + +}; + +Q_MOC_INCLUDE() + +#endif // MOC_INCLUDE_H diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index e5de647930..2bad8f2e63 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2013 Olivier Goffart +** Copyright (C) 2020 Olivier Goffart ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -27,8 +27,6 @@ ** ****************************************************************************/ - - #include #include #include @@ -74,6 +72,11 @@ #include "cxx17-namespaces.h" #include "cxx-attributes.h" +#include "moc_include.h" +#include "fwdclass1.h" +#include "fwdclass2.h" +#include "fwdclass3.h" + #ifdef Q_MOC_RUN // check that moc can parse these constructs, they are being used in Windows winsock2.h header #define STRING_HASH_HASH(x) ("foo" ## x ## "bar") @@ -717,6 +720,7 @@ private slots: void cxx17Namespaces(); void cxxAttributes(); void mocJsonOutput(); + void mocInclude(); signals: void sigWithUnsignedArg(unsigned foo); @@ -4002,6 +4006,29 @@ void tst_Moc::mocJsonOutput() QVERIFY2(actualOutput == expectedOutput, showPotentialDiff(actualOutput, expectedOutput).constData()); } +void TestFwdProperties::setProp1(const FwdClass1 &v) +{ + prop1.reset(new FwdClass1(v)); +} +void TestFwdProperties::setProp2(const FwdClass2 &v) +{ + prop2.reset(new FwdClass2(v)); +} +void TestFwdProperties::setProp3(const FwdClass3 &v) +{ + prop3.reset(new FwdClass3(v)); +} +TestFwdProperties::~TestFwdProperties() {} + +Q_DECLARE_METATYPE(FwdClass1); + +void tst_Moc::mocInclude() +{ + TestFwdProperties obj; + obj.setProperty("prop1", QVariant::fromValue(FwdClass1 { 45 })); + QCOMPARE(obj.prop1->x, 45); +} + QTEST_MAIN(tst_Moc) // the generated code must compile with QT_NO_KEYWORDS -- cgit v1.2.3