1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the tools applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #ifndef MOC_H
30 #define MOC_H
31 
32 #include "parser.h"
33 #include <qstringlist.h>
34 #include <qmap.h>
35 #include <qpair.h>
36 #include <qjsondocument.h>
37 #include <qjsonarray.h>
38 #include <qjsonobject.h>
39 #include <stdio.h>
40 #include <ctype.h>
41 
42 QT_BEGIN_NAMESPACE
43 
44 struct QMetaObject;
45 
46 struct Type
47 {
48     enum ReferenceType { NoReference, Reference, RValueReference, Pointer };
49 
TypeType50     inline Type() : isVolatile(false), isScoped(false), firstToken(NOTOKEN), referenceType(NoReference) {}
TypeType51     inline explicit Type(const QByteArray &_name)
52         : name(_name), rawName(name), isVolatile(false), isScoped(false), firstToken(NOTOKEN), referenceType(NoReference) {}
53     QByteArray name;
54     //When used as a return type, the type name may be modified to remove the references.
55     // rawName is the type as found in the function signature
56     QByteArray rawName;
57     uint isVolatile : 1;
58     uint isScoped : 1;
59     Token firstToken;
60     ReferenceType referenceType;
61 };
62 Q_DECLARE_TYPEINFO(Type, Q_MOVABLE_TYPE);
63 
64 struct ClassDef;
65 struct EnumDef
66 {
67     QByteArray name;
68     QByteArray enumName;
69     QVector<QByteArray> values;
70     bool isEnumClass; // c++11 enum class
EnumDefEnumDef71     EnumDef() : isEnumClass(false) {}
72     QJsonObject toJson(const ClassDef &cdef) const;
73 };
74 Q_DECLARE_TYPEINFO(EnumDef, Q_MOVABLE_TYPE);
75 
76 struct ArgumentDef
77 {
ArgumentDefArgumentDef78     ArgumentDef() : isDefault(false) {}
79     Type type;
80     QByteArray rightType, normalizedType, name;
81     QByteArray typeNameForCast; // type name to be used in cast from void * in metacall
82     bool isDefault;
83 
84     QJsonObject toJson() const;
85 };
86 Q_DECLARE_TYPEINFO(ArgumentDef, Q_MOVABLE_TYPE);
87 
88 struct FunctionDef
89 {
90     Type type;
91     QVector<ArgumentDef> arguments;
92     QByteArray normalizedType;
93     QByteArray tag;
94     QByteArray name;
95     QByteArray inPrivateClass;
96 
97     enum Access { Private, Protected, Public };
98     Access access = Private;
99     int revision = 0;
100 
101     bool isConst = false;
102     bool isVirtual = false;
103     bool isStatic = false;
104     bool inlineCode = false;
105     bool wasCloned = false;
106 
107     bool returnTypeIsVolatile = false;
108 
109     bool isCompat = false;
110     bool isInvokable = false;
111     bool isScriptable = false;
112     bool isSlot = false;
113     bool isSignal = false;
114     bool isPrivateSignal = false;
115     bool isConstructor = false;
116     bool isDestructor = false;
117     bool isAbstract = false;
118 
119     QJsonObject toJson() const;
120     static void accessToJson(QJsonObject *obj, Access acs);
121 };
122 Q_DECLARE_TYPEINFO(FunctionDef, Q_MOVABLE_TYPE);
123 
124 struct PropertyDef
125 {
stdCppSetPropertyDef126     bool stdCppSet() const {
127         QByteArray s("set");
128         s += toupper(name[0]);
129         s += name.mid(1);
130         return (s == write);
131     }
132 
133     QByteArray name, type, member, read, write, reset, designable, scriptable, editable, stored, user, notify, inPrivateClass;
134     int notifyId = -1; // -1 means no notifyId, >= 0 means signal defined in this class, < -1 means signal not defined in this class
135     enum Specification  { ValueSpec, ReferenceSpec, PointerSpec };
136     Specification gspec = ValueSpec;
137     int revision = 0;
138     bool constant = false;
139     bool final = false;
140     bool required = false;
141 
142     QJsonObject toJson() const;
143 };
144 Q_DECLARE_TYPEINFO(PropertyDef, Q_MOVABLE_TYPE);
145 
146 
147 struct ClassInfoDef
148 {
149     QByteArray name;
150     QByteArray value;
151 };
152 Q_DECLARE_TYPEINFO(ClassInfoDef, Q_MOVABLE_TYPE);
153 
154 struct BaseDef {
155     QByteArray classname;
156     QByteArray qualified;
157     QVector<ClassInfoDef> classInfoList;
158     QMap<QByteArray, bool> enumDeclarations;
159     QVector<EnumDef> enumList;
160     QMap<QByteArray, QByteArray> flagAliases;
161     int begin = 0;
162     int end = 0;
163 };
164 
165 struct ClassDef : BaseDef {
166     QVector<QPair<QByteArray, FunctionDef::Access> > superclassList;
167 
168     struct Interface
169     {
InterfaceClassDef::Interface170         Interface() {} // for QVector, don't use
InterfaceClassDef::Interface171         inline explicit Interface(const QByteArray &_className)
172             : className(_className) {}
173         QByteArray className;
174         QByteArray interfaceId;
175     };
176     QVector<QVector<Interface> >interfaceList;
177 
178     struct PluginData {
179         QByteArray iid;
180         QByteArray uri;
181         QMap<QString, QJsonArray> metaArgs;
182         QJsonDocument metaData;
183     } pluginData;
184 
185     QVector<FunctionDef> constructorList;
186     QVector<FunctionDef> signalList, slotList, methodList, publicList;
187     QVector<QByteArray> nonClassSignalList;
188     QVector<PropertyDef> propertyList;
189     int notifyableProperties = 0;
190     int revisionedMethods = 0;
191     int revisionedProperties = 0;
192 
193     bool hasQObject = false;
194     bool hasQGadget = false;
195     bool hasQNamespace = false;
196 
197     QJsonObject toJson() const;
198 };
199 Q_DECLARE_TYPEINFO(ClassDef, Q_MOVABLE_TYPE);
200 Q_DECLARE_TYPEINFO(ClassDef::Interface, Q_MOVABLE_TYPE);
201 
202 struct NamespaceDef : BaseDef {
203     bool hasQNamespace = false;
204     bool doGenerate = false;
205 };
206 Q_DECLARE_TYPEINFO(NamespaceDef, Q_MOVABLE_TYPE);
207 
208 class Moc : public Parser
209 {
210 public:
Moc()211     Moc()
212         : noInclude(false), mustIncludeQPluginH(false)
213         {}
214 
215     QByteArray filename;
216 
217     bool noInclude;
218     bool mustIncludeQPluginH;
219     QByteArray includePath;
220     QVector<QByteArray> includeFiles;
221     QVector<ClassDef> classList;
222     QMap<QByteArray, QByteArray> interface2IdMap;
223     QVector<QByteArray> metaTypes;
224     // map from class name to fully qualified name
225     QHash<QByteArray, QByteArray> knownQObjectClasses;
226     QHash<QByteArray, QByteArray> knownGadgets;
227     QMap<QString, QJsonArray> metaArgs;
228     QVector<QString> parsedPluginMetadataFiles;
229 
230     void parse();
231     void generate(FILE *out, FILE *jsonOutput);
232 
233     bool parseClassHead(ClassDef *def);
inClass(const ClassDef * def)234     inline bool inClass(const ClassDef *def) const {
235         return index > def->begin && index < def->end - 1;
236     }
237 
inNamespace(const NamespaceDef * def)238     inline bool inNamespace(const NamespaceDef *def) const {
239         return index > def->begin && index < def->end - 1;
240     }
241 
242     Type parseType();
243 
244     bool parseEnum(EnumDef *def);
245 
246     bool parseFunction(FunctionDef *def, bool inMacro = false);
247     bool parseMaybeFunction(const ClassDef *cdef, FunctionDef *def);
248 
249     void parseSlots(ClassDef *def, FunctionDef::Access access);
250     void parseSignals(ClassDef *def);
251     void parseProperty(ClassDef *def);
252     void parsePluginData(ClassDef *def);
253     void createPropertyDef(PropertyDef &def);
254     void parseEnumOrFlag(BaseDef *def, bool isFlag);
255     void parseFlag(BaseDef *def);
256     void parseClassInfo(BaseDef *def);
257     void parseInterfaces(ClassDef *def);
258     void parseDeclareInterface();
259     void parseDeclareMetatype();
260     void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access);
261     void parsePrivateProperty(ClassDef *def);
262 
263     void parseFunctionArguments(FunctionDef *def);
264 
265     QByteArray lexemUntil(Token);
266     bool until(Token);
267 
268     // test for Q_INVOCABLE, Q_SCRIPTABLE, etc. and set the flags
269     // in FunctionDef accordingly
270     bool testFunctionAttribute(FunctionDef *def);
271     bool testFunctionAttribute(Token tok, FunctionDef *def);
272     bool testFunctionRevision(FunctionDef *def);
273 
274     bool skipCxxAttributes();
275 
276     void checkSuperClasses(ClassDef *def);
277     void checkProperties(ClassDef* cdef);
278 };
279 
noRef(const QByteArray & type)280 inline QByteArray noRef(const QByteArray &type)
281 {
282     if (type.endsWith('&')) {
283         if (type.endsWith("&&"))
284             return type.left(type.length()-2);
285         return type.left(type.length()-1);
286     }
287     return type;
288 }
289 
290 QT_END_NAMESPACE
291 
292 #endif // MOC_H
293