##// END OF EJS Templates
changed special generated method prefix to py_, added py_toString() generation...
florianlink -
r115:5366b65bcedb
parent child
Show More
@@ -1,2634 +1,2634
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #include "abstractmetabuilder.h"
42 #include "abstractmetabuilder.h"
43 #include "reporthandler.h"
43 #include "reporthandler.h"
44
44
45 #include "ast.h"
45 #include "ast.h"
46 #include "binder.h"
46 #include "binder.h"
47 #include "control.h"
47 #include "control.h"
48 #include "default_visitor.h"
48 #include "default_visitor.h"
49 #include "dumptree.h"
49 #include "dumptree.h"
50 #include "lexer.h"
50 #include "lexer.h"
51 #include "parser.h"
51 #include "parser.h"
52 #include "tokens.h"
52 #include "tokens.h"
53
53
54 #include <QtCore/QDebug>
54 #include <QtCore/QDebug>
55 #include <QtCore/QFile>
55 #include <QtCore/QFile>
56 #include <QtCore/QFileInfo>
56 #include <QtCore/QFileInfo>
57 #include <QtCore/QTextCodec>
57 #include <QtCore/QTextCodec>
58 #include <QtCore/QTextStream>
58 #include <QtCore/QTextStream>
59 #include <QtCore/QVariant>
59 #include <QtCore/QVariant>
60
60
61 static QString strip_template_args(const QString &name)
61 static QString strip_template_args(const QString &name)
62 {
62 {
63 int pos = name.indexOf('<');
63 int pos = name.indexOf('<');
64 return pos < 0 ? name : name.left(pos);
64 return pos < 0 ? name : name.left(pos);
65 }
65 }
66
66
67 static QHash<QString, QString> *operator_names;
67 static QHash<QString, QString> *operator_names;
68 QString rename_operator(const QString &oper)
68 QString rename_operator(const QString &oper)
69 {
69 {
70 QString op = oper.trimmed();
70 QString op = oper.trimmed();
71 if (!operator_names) {
71 if (!operator_names) {
72 operator_names = new QHash<QString, QString>;
72 operator_names = new QHash<QString, QString>;
73
73
74 operator_names->insert("+", "__add__");
74 operator_names->insert("+", "__add__");
75 operator_names->insert("-", "__sub__");
75 operator_names->insert("-", "__sub__");
76 operator_names->insert("*", "__mul__");
76 operator_names->insert("*", "__mul__");
77 operator_names->insert("/", "__div__");
77 operator_names->insert("/", "__div__");
78 operator_names->insert("%", "__mod__");
78 operator_names->insert("%", "__mod__");
79 operator_names->insert("&", "__and__");
79 operator_names->insert("&", "__and__");
80 operator_names->insert("|", "__or__");
80 operator_names->insert("|", "__or__");
81 operator_names->insert("^", "__xor__");
81 operator_names->insert("^", "__xor__");
82 operator_names->insert("~", "__negate__");
82 operator_names->insert("~", "__negate__");
83 operator_names->insert("<<", "__lshift__");
83 operator_names->insert("<<", "__lshift__");
84 operator_names->insert(">>", "__rshift__");
84 operator_names->insert(">>", "__rshift__");
85
85
86 // assigments
86 // assigments
87 operator_names->insert("=", "assign");
87 operator_names->insert("=", "assign");
88 operator_names->insert("+=", "__iadd__");
88 operator_names->insert("+=", "__iadd__");
89 operator_names->insert("-=", "__isub__");
89 operator_names->insert("-=", "__isub__");
90 operator_names->insert("*=", "__imul__");
90 operator_names->insert("*=", "__imul__");
91 operator_names->insert("/=", "__idiv__");
91 operator_names->insert("/=", "__idiv__");
92 operator_names->insert("%=", "__imod__");
92 operator_names->insert("%=", "__imod__");
93 operator_names->insert("&=", "__iand__");
93 operator_names->insert("&=", "__iand__");
94 operator_names->insert("|=", "__ior__");
94 operator_names->insert("|=", "__ior__");
95 operator_names->insert("^=", "__ixor__");
95 operator_names->insert("^=", "__ixor__");
96 operator_names->insert("<<=", "__ilshift__");
96 operator_names->insert("<<=", "__ilshift__");
97 operator_names->insert(">>=", "__irshift__");
97 operator_names->insert(">>=", "__irshift__");
98
98
99 // Logical
99 // Logical
100 operator_names->insert("&&", "logical_and");
100 operator_names->insert("&&", "logical_and");
101 operator_names->insert("||", "logical_or");
101 operator_names->insert("||", "logical_or");
102 operator_names->insert("!", "not");
102 operator_names->insert("!", "not");
103
103
104 // incr/decr
104 // incr/decr
105 operator_names->insert("++", "increment");
105 operator_names->insert("++", "increment");
106 operator_names->insert("--", "decrement");
106 operator_names->insert("--", "decrement");
107
107
108 // compare
108 // compare
109 operator_names->insert("<", "less");
109 operator_names->insert("<", "less");
110 operator_names->insert(">", "greater");
110 operator_names->insert(">", "greater");
111 operator_names->insert("<=", "less_or_equal");
111 operator_names->insert("<=", "less_or_equal");
112 operator_names->insert(">=", "greater_or_equal");
112 operator_names->insert(">=", "greater_or_equal");
113 operator_names->insert("!=", "not_equal");
113 operator_names->insert("!=", "not_equal");
114 operator_names->insert("==", "equal");
114 operator_names->insert("==", "equal");
115
115
116 // other
116 // other
117 operator_names->insert("[]", "subscript");
117 operator_names->insert("[]", "subscript");
118 operator_names->insert("->", "pointer");
118 operator_names->insert("->", "pointer");
119 }
119 }
120
120
121 if (!operator_names->contains(op)) {
121 if (!operator_names->contains(op)) {
122 TypeDatabase *tb = TypeDatabase::instance();
122 TypeDatabase *tb = TypeDatabase::instance();
123
123
124 TypeParser::Info typeInfo = TypeParser::parse(op);
124 TypeParser::Info typeInfo = TypeParser::parse(op);
125 QString cast_to_name = typeInfo.qualified_name.join("::");
125 QString cast_to_name = typeInfo.qualified_name.join("::");
126 TypeEntry *te = tb->findType(cast_to_name);
126 TypeEntry *te = tb->findType(cast_to_name);
127 if ((te && te->codeGeneration() == TypeEntry::GenerateNothing)
127 if ((te && te->codeGeneration() == TypeEntry::GenerateNothing)
128 || tb->isClassRejected(cast_to_name)) {
128 || tb->isClassRejected(cast_to_name)) {
129 return QString();
129 return QString();
130 } else if (te) {
130 } else if (te) {
131 return "operator_cast_" + typeInfo.qualified_name.join("_");
131 return "operator_cast_" + typeInfo.qualified_name.join("_");
132 } else {
132 } else {
133 ReportHandler::warning(QString("unknown operator '%1'").arg(op));
133 ReportHandler::warning(QString("unknown operator '%1'").arg(op));
134 return "operator " + op;
134 return "operator " + op;
135 }
135 }
136 }
136 }
137
137
138 QString r = operator_names->value(op);
138 QString r = operator_names->value(op);
139 if (r.startsWith("__")) {
139 if (r.startsWith("__")) {
140 return r;
140 return r;
141 } else {
141 } else {
142 return "operator_" + r;
142 return "operator_" + r;
143 }
143 }
144 }
144 }
145
145
146 AbstractMetaBuilder::AbstractMetaBuilder()
146 AbstractMetaBuilder::AbstractMetaBuilder()
147 : m_current_class(0)
147 : m_current_class(0)
148 {
148 {
149 }
149 }
150
150
151 void AbstractMetaBuilder::checkFunctionModifications()
151 void AbstractMetaBuilder::checkFunctionModifications()
152 {
152 {
153 TypeDatabase *types = TypeDatabase::instance();
153 TypeDatabase *types = TypeDatabase::instance();
154 SingleTypeEntryHash entryHash = types->entries();
154 SingleTypeEntryHash entryHash = types->entries();
155 QList<TypeEntry *> entries = entryHash.values();
155 QList<TypeEntry *> entries = entryHash.values();
156 foreach (TypeEntry *entry, entries) {
156 foreach (TypeEntry *entry, entries) {
157 if (entry == 0)
157 if (entry == 0)
158 continue;
158 continue;
159 if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
159 if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
160 continue;
160 continue;
161
161
162 ComplexTypeEntry *centry = static_cast<ComplexTypeEntry *>(entry);
162 ComplexTypeEntry *centry = static_cast<ComplexTypeEntry *>(entry);
163 FunctionModificationList modifications = centry->functionModifications();
163 FunctionModificationList modifications = centry->functionModifications();
164
164
165 foreach (FunctionModification modification, modifications) {
165 foreach (FunctionModification modification, modifications) {
166 QString signature = modification.signature;
166 QString signature = modification.signature;
167
167
168 QString name = signature.trimmed();
168 QString name = signature.trimmed();
169 name = name.mid(0, signature.indexOf("("));
169 name = name.mid(0, signature.indexOf("("));
170
170
171 AbstractMetaClass *clazz = m_meta_classes.findClass(centry->qualifiedCppName());
171 AbstractMetaClass *clazz = m_meta_classes.findClass(centry->qualifiedCppName());
172 if (clazz == 0)
172 if (clazz == 0)
173 continue;
173 continue;
174
174
175 AbstractMetaFunctionList functions = clazz->functions();
175 AbstractMetaFunctionList functions = clazz->functions();
176 bool found = false;
176 bool found = false;
177 QStringList possibleSignatures;
177 QStringList possibleSignatures;
178 foreach (AbstractMetaFunction *function, functions) {
178 foreach (AbstractMetaFunction *function, functions) {
179 if (function->minimalSignature() == signature && function->implementingClass() == clazz) {
179 if (function->minimalSignature() == signature && function->implementingClass() == clazz) {
180 found = true;
180 found = true;
181 break;
181 break;
182 }
182 }
183
183
184 if (function->originalName() == name)
184 if (function->originalName() == name)
185 possibleSignatures.append(function->minimalSignature() + " in " + function->implementingClass()->name());
185 possibleSignatures.append(function->minimalSignature() + " in " + function->implementingClass()->name());
186 }
186 }
187
187
188 if (!found) {
188 if (!found) {
189 QString warning
189 QString warning
190 = QString("signature '%1' for function modification in '%2' not found. Possible candidates: %3")
190 = QString("signature '%1' for function modification in '%2' not found. Possible candidates: %3")
191 .arg(signature)
191 .arg(signature)
192 .arg(clazz->qualifiedCppName())
192 .arg(clazz->qualifiedCppName())
193 .arg(possibleSignatures.join(", "));
193 .arg(possibleSignatures.join(", "));
194
194
195 ReportHandler::warning(warning);
195 ReportHandler::warning(warning);
196 }
196 }
197 }
197 }
198 }
198 }
199 }
199 }
200
200
201 AbstractMetaClass *AbstractMetaBuilder::argumentToClass(ArgumentModelItem argument)
201 AbstractMetaClass *AbstractMetaBuilder::argumentToClass(ArgumentModelItem argument)
202 {
202 {
203 AbstractMetaClass *returned = 0;
203 AbstractMetaClass *returned = 0;
204 bool ok = false;
204 bool ok = false;
205 AbstractMetaType *type = translateType(argument->type(), &ok);
205 AbstractMetaType *type = translateType(argument->type(), &ok);
206 if (ok && type != 0 && type->typeEntry() != 0 && type->typeEntry()->isComplex()) {
206 if (ok && type != 0 && type->typeEntry() != 0 && type->typeEntry()->isComplex()) {
207 const TypeEntry *entry = type->typeEntry();
207 const TypeEntry *entry = type->typeEntry();
208 returned = m_meta_classes.findClass(entry->name());
208 returned = m_meta_classes.findClass(entry->name());
209 }
209 }
210 delete type;
210 delete type;
211 return returned;
211 return returned;
212 }
212 }
213
213
214 /**
214 /**
215 * Checks the argument of a hash function and flags the type if it is a complex type
215 * Checks the argument of a hash function and flags the type if it is a complex type
216 */
216 */
217 void AbstractMetaBuilder::registerHashFunction(FunctionModelItem function_item)
217 void AbstractMetaBuilder::registerHashFunction(FunctionModelItem function_item)
218 {
218 {
219 ArgumentList arguments = function_item->arguments();
219 ArgumentList arguments = function_item->arguments();
220 if (arguments.size() == 1) {
220 if (arguments.size() == 1) {
221 if (AbstractMetaClass *cls = argumentToClass(arguments.at(0)))
221 if (AbstractMetaClass *cls = argumentToClass(arguments.at(0)))
222 cls->setHasHashFunction(true);
222 cls->setHasHashFunction(true);
223 }
223 }
224 }
224 }
225
225
226 /**
226 /**
227 * Check if a class has a debug stream operator that can be used as toString
227 * Check if a class has a debug stream operator that can be used as toString
228 */
228 */
229
229
230 void AbstractMetaBuilder::registerToStringCapability(FunctionModelItem function_item)
230 void AbstractMetaBuilder::registerToStringCapability(FunctionModelItem function_item)
231 {
231 {
232 ArgumentList arguments = function_item->arguments();
232 ArgumentList arguments = function_item->arguments();
233 if (arguments.size() == 2) {
233 if (arguments.size() == 2) {
234 if (arguments.at(0)->type().toString() == "QDebug"){
234 if (arguments.at(0)->type().toString() == "QDebug"){
235 ArgumentModelItem arg = arguments.at(1);
235 ArgumentModelItem arg = arguments.at(1);
236 if (AbstractMetaClass *cls = argumentToClass(arg)) {
236 if (AbstractMetaClass *cls = argumentToClass(arg)) {
237 if (arg->type().indirections() < 2) {
237 if (arg->type().indirections() < 2 && cls->name()!="QObject") {
238 cls->setToStringCapability(function_item);
238 cls->setToStringCapability(function_item);
239 }
239 }
240 }
240 }
241 }
241 }
242 }
242 }
243 }
243 }
244
244
245 void AbstractMetaBuilder::traverseCompareOperator(FunctionModelItem item) {
245 void AbstractMetaBuilder::traverseCompareOperator(FunctionModelItem item) {
246 ArgumentList arguments = item->arguments();
246 ArgumentList arguments = item->arguments();
247 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
247 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
248 AbstractMetaClass *comparer_class = argumentToClass(arguments.at(0));
248 AbstractMetaClass *comparer_class = argumentToClass(arguments.at(0));
249 AbstractMetaClass *compared_class = argumentToClass(arguments.at(1));
249 AbstractMetaClass *compared_class = argumentToClass(arguments.at(1));
250 if (comparer_class != 0 && compared_class != 0) {
250 if (comparer_class != 0 && compared_class != 0) {
251 AbstractMetaClass *old_current_class = m_current_class;
251 AbstractMetaClass *old_current_class = m_current_class;
252 m_current_class = comparer_class;
252 m_current_class = comparer_class;
253
253
254 AbstractMetaFunction *meta_function = traverseFunction(item);
254 AbstractMetaFunction *meta_function = traverseFunction(item);
255 if (meta_function != 0 && !meta_function->isInvalid()) {
255 if (meta_function != 0 && !meta_function->isInvalid()) {
256 // Strip away first argument, since that is the containing object
256 // Strip away first argument, since that is the containing object
257 AbstractMetaArgumentList arguments = meta_function->arguments();
257 AbstractMetaArgumentList arguments = meta_function->arguments();
258 arguments.pop_front();
258 arguments.pop_front();
259 meta_function->setArguments(arguments);
259 meta_function->setArguments(arguments);
260
260
261 meta_function->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
261 meta_function->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
262
262
263 meta_function->setOriginalAttributes(meta_function->attributes());
263 meta_function->setOriginalAttributes(meta_function->attributes());
264 setupFunctionDefaults(meta_function, comparer_class);
264 setupFunctionDefaults(meta_function, comparer_class);
265
265
266 comparer_class->addFunction(meta_function);
266 comparer_class->addFunction(meta_function);
267 } else if (meta_function != 0) {
267 } else if (meta_function != 0) {
268 delete meta_function;
268 delete meta_function;
269 }
269 }
270
270
271 m_current_class = old_current_class;
271 m_current_class = old_current_class;
272 }
272 }
273 }
273 }
274 }
274 }
275
275
276 void AbstractMetaBuilder::traverseStreamOperator(FunctionModelItem item)
276 void AbstractMetaBuilder::traverseStreamOperator(FunctionModelItem item)
277 {
277 {
278 ArgumentList arguments = item->arguments();
278 ArgumentList arguments = item->arguments();
279 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
279 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
280 AbstractMetaClass *streamClass = argumentToClass(arguments.at(0));
280 AbstractMetaClass *streamClass = argumentToClass(arguments.at(0));
281 AbstractMetaClass *streamedClass = argumentToClass(arguments.at(1));
281 AbstractMetaClass *streamedClass = argumentToClass(arguments.at(1));
282
282
283 if (streamClass != 0 && streamedClass != 0
283 if (streamClass != 0 && streamedClass != 0
284 && (streamClass->name() == "QDataStream" || streamClass->name() == "QTextStream")) {
284 && (streamClass->name() == "QDataStream" || streamClass->name() == "QTextStream")) {
285 AbstractMetaClass *old_current_class = m_current_class;
285 AbstractMetaClass *old_current_class = m_current_class;
286 m_current_class = streamedClass;
286 m_current_class = streamedClass;
287 AbstractMetaFunction *streamFunction = traverseFunction(item);
287 AbstractMetaFunction *streamFunction = traverseFunction(item);
288
288
289 if (streamFunction != 0 && !streamFunction->isInvalid()) {
289 if (streamFunction != 0 && !streamFunction->isInvalid()) {
290 QString name = item->name();
290 QString name = item->name();
291 streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
291 streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
292
292
293 if (name.endsWith("<<"))
293 if (name.endsWith("<<"))
294 streamFunction->setName("writeTo");
294 streamFunction->setName("writeTo");
295 else
295 else
296 streamFunction->setName("readFrom");
296 streamFunction->setName("readFrom");
297
297
298 // Strip away last argument, since that is the containing object
298 // Strip away last argument, since that is the containing object
299 AbstractMetaArgumentList arguments = streamFunction->arguments();
299 AbstractMetaArgumentList arguments = streamFunction->arguments();
300 arguments.pop_back();
300 arguments.pop_back();
301 streamFunction->setArguments(arguments);
301 streamFunction->setArguments(arguments);
302
302
303 *streamFunction += AbstractMetaAttributes::Final;
303 *streamFunction += AbstractMetaAttributes::Final;
304 *streamFunction += AbstractMetaAttributes::Public;
304 *streamFunction += AbstractMetaAttributes::Public;
305 streamFunction->setOriginalAttributes(streamFunction->attributes());
305 streamFunction->setOriginalAttributes(streamFunction->attributes());
306
306
307 streamFunction->setType(0);
307 streamFunction->setType(0);
308
308
309 setupFunctionDefaults(streamFunction, streamedClass);
309 setupFunctionDefaults(streamFunction, streamedClass);
310
310
311 streamedClass->addFunction(streamFunction);
311 streamedClass->addFunction(streamFunction);
312 streamedClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
312 streamedClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
313
313
314 m_current_class = old_current_class;
314 m_current_class = old_current_class;
315 }
315 }
316 }
316 }
317 }
317 }
318 }
318 }
319
319
320 void AbstractMetaBuilder::traverseBinaryArithmeticOperator(FunctionModelItem item)
320 void AbstractMetaBuilder::traverseBinaryArithmeticOperator(FunctionModelItem item)
321 {
321 {
322 ArgumentList arguments = item->arguments();
322 ArgumentList arguments = item->arguments();
323 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
323 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
324 AbstractMetaClass *aClass = argumentToClass(arguments.at(0));
324 AbstractMetaClass *aClass = argumentToClass(arguments.at(0));
325 AbstractMetaClass *bClass = argumentToClass(arguments.at(1));
325 AbstractMetaClass *bClass = argumentToClass(arguments.at(1));
326
326
327 if (!aClass) return;
327 if (!aClass) return;
328
328
329 AbstractMetaClass *old_current_class = m_current_class;
329 AbstractMetaClass *old_current_class = m_current_class;
330 m_current_class = aClass;
330 m_current_class = aClass;
331 AbstractMetaFunction *streamFunction = traverseFunction(item);
331 AbstractMetaFunction *streamFunction = traverseFunction(item);
332 if (streamFunction != 0 && !streamFunction->isInvalid()) {
332 if (streamFunction != 0 && !streamFunction->isInvalid()) {
333 QString name = rename_operator(item->name().mid(8));
333 QString name = rename_operator(item->name().mid(8));
334 if (name.isEmpty()) return;
334 if (name.isEmpty()) return;
335
335
336 streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
336 streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
337 streamFunction->setName(name);
337 streamFunction->setName(name);
338
338
339 // Strip away the first argument, since that is the operator object
339 // Strip away the first argument, since that is the operator object
340 AbstractMetaArgumentList arguments = streamFunction->arguments();
340 AbstractMetaArgumentList arguments = streamFunction->arguments();
341 arguments.removeFirst();
341 arguments.removeFirst();
342 streamFunction->setArguments(arguments);
342 streamFunction->setArguments(arguments);
343
343
344 *streamFunction += AbstractMetaAttributes::Final;
344 *streamFunction += AbstractMetaAttributes::Final;
345 *streamFunction += AbstractMetaAttributes::Public;
345 *streamFunction += AbstractMetaAttributes::Public;
346 streamFunction->setOriginalAttributes(streamFunction->attributes());
346 streamFunction->setOriginalAttributes(streamFunction->attributes());
347
347
348 setupFunctionDefaults(streamFunction, aClass);
348 setupFunctionDefaults(streamFunction, aClass);
349
349
350 aClass->addFunction(streamFunction);
350 aClass->addFunction(streamFunction);
351 if (bClass) {
351 if (bClass) {
352 aClass->typeEntry()->addExtraInclude(bClass->typeEntry()->include());
352 aClass->typeEntry()->addExtraInclude(bClass->typeEntry()->include());
353 }
353 }
354
354
355 m_current_class = old_current_class;
355 m_current_class = old_current_class;
356 }
356 }
357 }
357 }
358 }
358 }
359
359
360 void AbstractMetaBuilder::fixQObjectForScope(TypeDatabase *types,
360 void AbstractMetaBuilder::fixQObjectForScope(TypeDatabase *types,
361 NamespaceModelItem scope)
361 NamespaceModelItem scope)
362 {
362 {
363 foreach (ClassModelItem item, scope->classes()) {
363 foreach (ClassModelItem item, scope->classes()) {
364 QString qualified_name = item->qualifiedName().join("::");
364 QString qualified_name = item->qualifiedName().join("::");
365 TypeEntry *entry = types->findType(qualified_name);
365 TypeEntry *entry = types->findType(qualified_name);
366 if (entry) {
366 if (entry) {
367 if (isQObject(qualified_name) && entry->isComplex()) {
367 if (isQObject(qualified_name) && entry->isComplex()) {
368 ((ComplexTypeEntry *) entry)->setQObject(true);
368 ((ComplexTypeEntry *) entry)->setQObject(true);
369 }
369 }
370 }
370 }
371 }
371 }
372
372
373 foreach (NamespaceModelItem item, scope->namespaceMap().values()) {
373 foreach (NamespaceModelItem item, scope->namespaceMap().values()) {
374 if (scope != item)
374 if (scope != item)
375 fixQObjectForScope(types, item);
375 fixQObjectForScope(types, item);
376 }
376 }
377 }
377 }
378
378
379 static bool class_less_than(AbstractMetaClass *a, AbstractMetaClass *b)
379 static bool class_less_than(AbstractMetaClass *a, AbstractMetaClass *b)
380 {
380 {
381 return a->name() < b->name();
381 return a->name() < b->name();
382 }
382 }
383
383
384
384
385 void AbstractMetaBuilder::sortLists()
385 void AbstractMetaBuilder::sortLists()
386 {
386 {
387 qSort(m_meta_classes.begin(), m_meta_classes.end(), class_less_than);
387 qSort(m_meta_classes.begin(), m_meta_classes.end(), class_less_than);
388 foreach (AbstractMetaClass *cls, m_meta_classes) {
388 foreach (AbstractMetaClass *cls, m_meta_classes) {
389 cls->sortFunctions();
389 cls->sortFunctions();
390 }
390 }
391 }
391 }
392
392
393 bool AbstractMetaBuilder::build()
393 bool AbstractMetaBuilder::build()
394 {
394 {
395 Q_ASSERT(!m_file_name.isEmpty());
395 Q_ASSERT(!m_file_name.isEmpty());
396
396
397 QFile file(m_file_name);
397 QFile file(m_file_name);
398
398
399 if (!file.open(QFile::ReadOnly))
399 if (!file.open(QFile::ReadOnly))
400 return false;
400 return false;
401
401
402 QTextStream stream(&file);
402 QTextStream stream(&file);
403 stream.setCodec(QTextCodec::codecForName("UTF-8"));
403 stream.setCodec(QTextCodec::codecForName("UTF-8"));
404 QByteArray contents = stream.readAll().toUtf8();
404 QByteArray contents = stream.readAll().toUtf8();
405 file.close();
405 file.close();
406
406
407 Control control;
407 Control control;
408 Parser p(&control);
408 Parser p(&control);
409 pool __pool;
409 pool __pool;
410
410
411 TranslationUnitAST *ast = p.parse(contents, contents.size(), &__pool);
411 TranslationUnitAST *ast = p.parse(contents, contents.size(), &__pool);
412
412
413 CodeModel model;
413 CodeModel model;
414 Binder binder(&model, p.location());
414 Binder binder(&model, p.location());
415 m_dom = binder.run(ast);
415 m_dom = binder.run(ast);
416
416
417 pushScope(model_dynamic_cast<ScopeModelItem>(m_dom));
417 pushScope(model_dynamic_cast<ScopeModelItem>(m_dom));
418
418
419 QHash<QString, ClassModelItem> typeMap = m_dom->classMap();
419 QHash<QString, ClassModelItem> typeMap = m_dom->classMap();
420
420
421
421
422 // fix up QObject's in the type system..
422 // fix up QObject's in the type system..
423 TypeDatabase *types = TypeDatabase::instance();
423 TypeDatabase *types = TypeDatabase::instance();
424 fixQObjectForScope(types, model_dynamic_cast<NamespaceModelItem>(m_dom));
424 fixQObjectForScope(types, model_dynamic_cast<NamespaceModelItem>(m_dom));
425
425
426
426
427 // Start the generation...
427 // Start the generation...
428 foreach (ClassModelItem item, typeMap.values()) {
428 foreach (ClassModelItem item, typeMap.values()) {
429 AbstractMetaClass *cls = traverseClass(item);
429 AbstractMetaClass *cls = traverseClass(item);
430 addAbstractMetaClass(cls);
430 addAbstractMetaClass(cls);
431 }
431 }
432
432
433
433
434 QHash<QString, NamespaceModelItem> namespaceMap = m_dom->namespaceMap();
434 QHash<QString, NamespaceModelItem> namespaceMap = m_dom->namespaceMap();
435 foreach (NamespaceModelItem item, namespaceMap.values()) {
435 foreach (NamespaceModelItem item, namespaceMap.values()) {
436 AbstractMetaClass *meta_class = traverseNamespace(item);
436 AbstractMetaClass *meta_class = traverseNamespace(item);
437 if (meta_class)
437 if (meta_class)
438 m_meta_classes << meta_class;
438 m_meta_classes << meta_class;
439 }
439 }
440
440
441
441
442 // Some trickery to support global-namespace enums...
442 // Some trickery to support global-namespace enums...
443 QHash<QString, EnumModelItem> enumMap = m_dom->enumMap();
443 QHash<QString, EnumModelItem> enumMap = m_dom->enumMap();
444 m_current_class = 0;
444 m_current_class = 0;
445 foreach (EnumModelItem item, enumMap) {
445 foreach (EnumModelItem item, enumMap) {
446 AbstractMetaEnum *meta_enum = traverseEnum(item, 0, QSet<QString>());
446 AbstractMetaEnum *meta_enum = traverseEnum(item, 0, QSet<QString>());
447
447
448 if (meta_enum) {
448 if (meta_enum) {
449 QString package = meta_enum->typeEntry()->javaPackage();
449 QString package = meta_enum->typeEntry()->javaPackage();
450 QString globalName = TypeDatabase::globalNamespaceClassName(meta_enum->typeEntry());
450 QString globalName = TypeDatabase::globalNamespaceClassName(meta_enum->typeEntry());
451
451
452 AbstractMetaClass *global = m_meta_classes.findClass(package + "." + globalName);
452 AbstractMetaClass *global = m_meta_classes.findClass(package + "." + globalName);
453 if (!global) {
453 if (!global) {
454 ComplexTypeEntry *gte = new ObjectTypeEntry(globalName);
454 ComplexTypeEntry *gte = new ObjectTypeEntry(globalName);
455 gte->setTargetLangPackage(meta_enum->typeEntry()->javaPackage());
455 gte->setTargetLangPackage(meta_enum->typeEntry()->javaPackage());
456 gte->setCodeGeneration(meta_enum->typeEntry()->codeGeneration());
456 gte->setCodeGeneration(meta_enum->typeEntry()->codeGeneration());
457 global = createMetaClass();
457 global = createMetaClass();
458 global->setTypeEntry(gte);
458 global->setTypeEntry(gte);
459 *global += AbstractMetaAttributes::Final;
459 *global += AbstractMetaAttributes::Final;
460 *global += AbstractMetaAttributes::Public;
460 *global += AbstractMetaAttributes::Public;
461 *global += AbstractMetaAttributes::Fake;
461 *global += AbstractMetaAttributes::Fake;
462
462
463 m_meta_classes << global;
463 m_meta_classes << global;
464 }
464 }
465
465
466 global->addEnum(meta_enum);
466 global->addEnum(meta_enum);
467 meta_enum->setEnclosingClass(global);
467 meta_enum->setEnclosingClass(global);
468 meta_enum->typeEntry()->setQualifier(globalName);
468 meta_enum->typeEntry()->setQualifier(globalName);
469
469
470 // Global enums should be public despite not having public
470 // Global enums should be public despite not having public
471 // identifiers so we'll fix the original attributes here.
471 // identifiers so we'll fix the original attributes here.
472 meta_enum->setOriginalAttributes(meta_enum->attributes());
472 meta_enum->setOriginalAttributes(meta_enum->attributes());
473 }
473 }
474
474
475
475
476 }
476 }
477
477
478
478
479 // Go through all typedefs to see if we have defined any
479 // Go through all typedefs to see if we have defined any
480 // specific typedefs to be used as classes.
480 // specific typedefs to be used as classes.
481 TypeAliasList typeAliases = m_dom->typeAliases();
481 TypeAliasList typeAliases = m_dom->typeAliases();
482 foreach (TypeAliasModelItem typeAlias, typeAliases) {
482 foreach (TypeAliasModelItem typeAlias, typeAliases) {
483 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
483 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
484 addAbstractMetaClass(cls);
484 addAbstractMetaClass(cls);
485 }
485 }
486
486
487
487
488
488
489
489
490 foreach (AbstractMetaClass *cls, m_meta_classes) {
490 foreach (AbstractMetaClass *cls, m_meta_classes) {
491 if (!cls->isInterface() && !cls->isNamespace()) {
491 if (!cls->isInterface() && !cls->isNamespace()) {
492 setupInheritance(cls);
492 setupInheritance(cls);
493 }
493 }
494 }
494 }
495
495
496
496
497 foreach (AbstractMetaClass *cls, m_meta_classes) {
497 foreach (AbstractMetaClass *cls, m_meta_classes) {
498 cls->fixFunctions();
498 cls->fixFunctions();
499
499
500 if (cls->typeEntry() == 0) {
500 if (cls->typeEntry() == 0) {
501 ReportHandler::warning(QString("class '%1' does not have an entry in the type system")
501 ReportHandler::warning(QString("class '%1' does not have an entry in the type system")
502 .arg(cls->name()));
502 .arg(cls->name()));
503 } else {
503 } else {
504 if (!cls->hasConstructors() && !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace())
504 if (!cls->hasConstructors() && !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace())
505 cls->addDefaultConstructor();
505 cls->addDefaultConstructor();
506 }
506 }
507
507
508 if (cls->isAbstract() && !cls->isInterface()) {
508 if (cls->isAbstract() && !cls->isInterface()) {
509 cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + "$ConcreteWrapper");
509 cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + "$ConcreteWrapper");
510 }
510 }
511 }
511 }
512
512
513 QList<TypeEntry *> entries = TypeDatabase::instance()->entries().values();
513 QList<TypeEntry *> entries = TypeDatabase::instance()->entries().values();
514 foreach (const TypeEntry *entry, entries) {
514 foreach (const TypeEntry *entry, entries) {
515 if (entry->isPrimitive())
515 if (entry->isPrimitive())
516 continue;
516 continue;
517
517
518 if ((entry->isValue() || entry->isObject())
518 if ((entry->isValue() || entry->isObject())
519 && !entry->isString()
519 && !entry->isString()
520 && !entry->isChar()
520 && !entry->isChar()
521 && !entry->isContainer()
521 && !entry->isContainer()
522 && !entry->isCustom()
522 && !entry->isCustom()
523 && !entry->isVariant()
523 && !entry->isVariant()
524 && !m_meta_classes.findClass(entry->qualifiedCppName())) {
524 && !m_meta_classes.findClass(entry->qualifiedCppName())) {
525 ReportHandler::warning(QString("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
525 ReportHandler::warning(QString("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
526 .arg(entry->qualifiedCppName()));
526 .arg(entry->qualifiedCppName()));
527 }
527 }
528
528
529 if (entry->isEnum()) {
529 if (entry->isEnum()) {
530 QString pkg = entry->javaPackage();
530 QString pkg = entry->javaPackage();
531 QString name = (pkg.isEmpty() ? QString() : pkg + ".")
531 QString name = (pkg.isEmpty() ? QString() : pkg + ".")
532 + ((EnumTypeEntry *) entry)->javaQualifier();
532 + ((EnumTypeEntry *) entry)->javaQualifier();
533 AbstractMetaClass *cls = m_meta_classes.findClass(name);
533 AbstractMetaClass *cls = m_meta_classes.findClass(name);
534
534
535 if (!cls) {
535 if (!cls) {
536 ReportHandler::warning(QString("namespace '%1' for enum '%2' is not declared")
536 ReportHandler::warning(QString("namespace '%1' for enum '%2' is not declared")
537 .arg(name).arg(entry->targetLangName()));
537 .arg(name).arg(entry->targetLangName()));
538 } else {
538 } else {
539 AbstractMetaEnum *e = cls->findEnum(entry->targetLangName());
539 AbstractMetaEnum *e = cls->findEnum(entry->targetLangName());
540 if (!e)
540 if (!e)
541 ReportHandler::warning(QString("enum '%1' is specified in typesystem, "
541 ReportHandler::warning(QString("enum '%1' is specified in typesystem, "
542 "but not declared")
542 "but not declared")
543 .arg(entry->qualifiedCppName()));
543 .arg(entry->qualifiedCppName()));
544 }
544 }
545 }
545 }
546 }
546 }
547
547
548 {
548 {
549 FunctionList hash_functions = m_dom->findFunctions("qHash");
549 FunctionList hash_functions = m_dom->findFunctions("qHash");
550 foreach (FunctionModelItem item, hash_functions) {
550 foreach (FunctionModelItem item, hash_functions) {
551 registerHashFunction(item);
551 registerHashFunction(item);
552 }
552 }
553 }
553 }
554
554
555 {
555 {
556 FunctionList hash_functions = m_dom->findFunctions("operator<<");
556 FunctionList hash_functions = m_dom->findFunctions("operator<<");
557 foreach (FunctionModelItem item, hash_functions) {
557 foreach (FunctionModelItem item, hash_functions) {
558 registerToStringCapability(item);
558 registerToStringCapability(item);
559 }
559 }
560 }
560 }
561
561
562 {
562 {
563 FunctionList compare_operators = m_dom->findFunctions("operator==")
563 FunctionList compare_operators = m_dom->findFunctions("operator==")
564 + m_dom->findFunctions("operator<=")
564 + m_dom->findFunctions("operator<=")
565 + m_dom->findFunctions("operator>=")
565 + m_dom->findFunctions("operator>=")
566 + m_dom->findFunctions("operator<")
566 + m_dom->findFunctions("operator<")
567 + m_dom->findFunctions("operator>");
567 + m_dom->findFunctions("operator>");
568 foreach (FunctionModelItem item, compare_operators) {
568 foreach (FunctionModelItem item, compare_operators) {
569 traverseCompareOperator(item);
569 traverseCompareOperator(item);
570 }
570 }
571 }
571 }
572
572
573 {
573 {
574 FunctionList stream_operators =
574 FunctionList stream_operators =
575 m_dom->findFunctions("operator+") + m_dom->findFunctions("operator-")
575 m_dom->findFunctions("operator+") + m_dom->findFunctions("operator-")
576 + m_dom->findFunctions("operator/") + m_dom->findFunctions("operator*")
576 + m_dom->findFunctions("operator/") + m_dom->findFunctions("operator*")
577 + m_dom->findFunctions("operator&") + m_dom->findFunctions("operator|")
577 + m_dom->findFunctions("operator&") + m_dom->findFunctions("operator|")
578 + m_dom->findFunctions("operator%") + m_dom->findFunctions("operator^");
578 + m_dom->findFunctions("operator%") + m_dom->findFunctions("operator^");
579 foreach (FunctionModelItem item, stream_operators) {
579 foreach (FunctionModelItem item, stream_operators) {
580 traverseBinaryArithmeticOperator(item);
580 traverseBinaryArithmeticOperator(item);
581 }
581 }
582 }
582 }
583 {
583 {
584 FunctionList stream_operators = m_dom->findFunctions("operator<<") + m_dom->findFunctions("operator>>");
584 FunctionList stream_operators = m_dom->findFunctions("operator<<") + m_dom->findFunctions("operator>>");
585 foreach (FunctionModelItem item, stream_operators) {
585 foreach (FunctionModelItem item, stream_operators) {
586 traverseStreamOperator(item);
586 traverseStreamOperator(item);
587 }
587 }
588 }
588 }
589
589
590 figureOutEnumValues();
590 figureOutEnumValues();
591 figureOutDefaultEnumArguments();
591 figureOutDefaultEnumArguments();
592 checkFunctionModifications();
592 checkFunctionModifications();
593
593
594 foreach (AbstractMetaClass *cls, m_meta_classes) {
594 foreach (AbstractMetaClass *cls, m_meta_classes) {
595 setupEquals(cls);
595 setupEquals(cls);
596 setupComparable(cls);
596 setupComparable(cls);
597 setupClonable(cls);
597 setupClonable(cls);
598 }
598 }
599
599
600 dumpLog();
600 dumpLog();
601
601
602 sortLists();
602 sortLists();
603
603
604 return true;
604 return true;
605 }
605 }
606
606
607
607
608 void AbstractMetaBuilder::addAbstractMetaClass(AbstractMetaClass *cls)
608 void AbstractMetaBuilder::addAbstractMetaClass(AbstractMetaClass *cls)
609 {
609 {
610 if (!cls)
610 if (!cls)
611 return;
611 return;
612
612
613 cls->setOriginalAttributes(cls->attributes());
613 cls->setOriginalAttributes(cls->attributes());
614 if (cls->typeEntry()->isContainer()) {
614 if (cls->typeEntry()->isContainer()) {
615 m_templates << cls;
615 m_templates << cls;
616 } else {
616 } else {
617 m_meta_classes << cls;
617 m_meta_classes << cls;
618 if (cls->typeEntry()->designatedInterface()) {
618 if (cls->typeEntry()->designatedInterface()) {
619 AbstractMetaClass *interface = cls->extractInterface();
619 AbstractMetaClass *interface = cls->extractInterface();
620 m_meta_classes << interface;
620 m_meta_classes << interface;
621 ReportHandler::debugSparse(QString(" -> interface '%1'").arg(interface->name()));
621 ReportHandler::debugSparse(QString(" -> interface '%1'").arg(interface->name()));
622 }
622 }
623 }
623 }
624 }
624 }
625
625
626
626
627 AbstractMetaClass *AbstractMetaBuilder::traverseNamespace(NamespaceModelItem namespace_item)
627 AbstractMetaClass *AbstractMetaBuilder::traverseNamespace(NamespaceModelItem namespace_item)
628 {
628 {
629 QString namespace_name = (!m_namespace_prefix.isEmpty() ? m_namespace_prefix + "::" : QString()) + namespace_item->name();
629 QString namespace_name = (!m_namespace_prefix.isEmpty() ? m_namespace_prefix + "::" : QString()) + namespace_item->name();
630 NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespace_name);
630 NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespace_name);
631
631
632 if (TypeDatabase::instance()->isClassRejected(namespace_name)) {
632 if (TypeDatabase::instance()->isClassRejected(namespace_name)) {
633 m_rejected_classes.insert(namespace_name, GenerationDisabled);
633 m_rejected_classes.insert(namespace_name, GenerationDisabled);
634 return 0;
634 return 0;
635 }
635 }
636
636
637 if (!type) {
637 if (!type) {
638 ReportHandler::warning(QString("namespace '%1' does not have a type entry")
638 ReportHandler::warning(QString("namespace '%1' does not have a type entry")
639 .arg(namespace_name));
639 .arg(namespace_name));
640 return 0;
640 return 0;
641 }
641 }
642
642
643 AbstractMetaClass *meta_class = createMetaClass();
643 AbstractMetaClass *meta_class = createMetaClass();
644 meta_class->setTypeEntry(type);
644 meta_class->setTypeEntry(type);
645
645
646 *meta_class += AbstractMetaAttributes::Public;
646 *meta_class += AbstractMetaAttributes::Public;
647
647
648 m_current_class = meta_class;
648 m_current_class = meta_class;
649
649
650 ReportHandler::debugSparse(QString("namespace '%1.%2'")
650 ReportHandler::debugSparse(QString("namespace '%1.%2'")
651 .arg(meta_class->package())
651 .arg(meta_class->package())
652 .arg(namespace_item->name()));
652 .arg(namespace_item->name()));
653
653
654 traverseEnums(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class, namespace_item->enumsDeclarations());
654 traverseEnums(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class, namespace_item->enumsDeclarations());
655 traverseFunctions(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class);
655 traverseFunctions(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class);
656 // traverseClasses(model_dynamic_cast<ScopeModelItem>(namespace_item));
656 // traverseClasses(model_dynamic_cast<ScopeModelItem>(namespace_item));
657
657
658 pushScope(model_dynamic_cast<ScopeModelItem>(namespace_item));
658 pushScope(model_dynamic_cast<ScopeModelItem>(namespace_item));
659 m_namespace_prefix = currentScope()->qualifiedName().join("::");
659 m_namespace_prefix = currentScope()->qualifiedName().join("::");
660
660
661
661
662 ClassList classes = namespace_item->classes();
662 ClassList classes = namespace_item->classes();
663 foreach (ClassModelItem cls, classes) {
663 foreach (ClassModelItem cls, classes) {
664 AbstractMetaClass *mjc = traverseClass(cls);
664 AbstractMetaClass *mjc = traverseClass(cls);
665 addAbstractMetaClass(mjc);
665 addAbstractMetaClass(mjc);
666 }
666 }
667
667
668 // Go through all typedefs to see if we have defined any
668 // Go through all typedefs to see if we have defined any
669 // specific typedefs to be used as classes.
669 // specific typedefs to be used as classes.
670 TypeAliasList typeAliases = namespace_item->typeAliases();
670 TypeAliasList typeAliases = namespace_item->typeAliases();
671 foreach (TypeAliasModelItem typeAlias, typeAliases) {
671 foreach (TypeAliasModelItem typeAlias, typeAliases) {
672 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
672 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
673 addAbstractMetaClass(cls);
673 addAbstractMetaClass(cls);
674 }
674 }
675
675
676
676
677
677
678 // Traverse namespaces recursively
678 // Traverse namespaces recursively
679 QList<NamespaceModelItem> inner_namespaces = namespace_item->namespaceMap().values();
679 QList<NamespaceModelItem> inner_namespaces = namespace_item->namespaceMap().values();
680 foreach (const NamespaceModelItem &ni, inner_namespaces) {
680 foreach (const NamespaceModelItem &ni, inner_namespaces) {
681 AbstractMetaClass *mjc = traverseNamespace(ni);
681 AbstractMetaClass *mjc = traverseNamespace(ni);
682 addAbstractMetaClass(mjc);
682 addAbstractMetaClass(mjc);
683 }
683 }
684
684
685 m_current_class = 0;
685 m_current_class = 0;
686
686
687
687
688 popScope();
688 popScope();
689 m_namespace_prefix = currentScope()->qualifiedName().join("::");
689 m_namespace_prefix = currentScope()->qualifiedName().join("::");
690
690
691 if (!type->include().isValid()) {
691 if (!type->include().isValid()) {
692 QFileInfo info(namespace_item->fileName());
692 QFileInfo info(namespace_item->fileName());
693 type->setInclude(Include(Include::IncludePath, info.fileName()));
693 type->setInclude(Include(Include::IncludePath, info.fileName()));
694 }
694 }
695
695
696 return meta_class;
696 return meta_class;
697 }
697 }
698
698
699 struct Operator
699 struct Operator
700 {
700 {
701 enum Type { Plus, ShiftLeft, None };
701 enum Type { Plus, ShiftLeft, None };
702
702
703 Operator() : type(None) { }
703 Operator() : type(None) { }
704
704
705 int calculate(int x) {
705 int calculate(int x) {
706 switch (type) {
706 switch (type) {
707 case Plus: return x + value;
707 case Plus: return x + value;
708 case ShiftLeft: return x << value;
708 case ShiftLeft: return x << value;
709 case None: return x;
709 case None: return x;
710 }
710 }
711 return x;
711 return x;
712 }
712 }
713
713
714 Type type;
714 Type type;
715 int value;
715 int value;
716 };
716 };
717
717
718
718
719
719
720 Operator findOperator(QString *s) {
720 Operator findOperator(QString *s) {
721 const char *names[] = {
721 const char *names[] = {
722 "+",
722 "+",
723 "<<"
723 "<<"
724 };
724 };
725
725
726 for (int i=0; i<Operator::None; ++i) {
726 for (int i=0; i<Operator::None; ++i) {
727 QString name = QLatin1String(names[i]);
727 QString name = QLatin1String(names[i]);
728 QString str = *s;
728 QString str = *s;
729 int splitPoint = str.indexOf(name);
729 int splitPoint = str.indexOf(name);
730 if (splitPoint > 0) {
730 if (splitPoint > 0) {
731 bool ok;
731 bool ok;
732 QString right = str.mid(splitPoint + name.length());
732 QString right = str.mid(splitPoint + name.length());
733 Operator op;
733 Operator op;
734 op.value = right.toInt(&ok);
734 op.value = right.toInt(&ok);
735 if (ok) {
735 if (ok) {
736 op.type = Operator::Type(i);
736 op.type = Operator::Type(i);
737 *s = str.left(splitPoint).trimmed();
737 *s = str.left(splitPoint).trimmed();
738 return op;
738 return op;
739 }
739 }
740 }
740 }
741 }
741 }
742 return Operator();
742 return Operator();
743 }
743 }
744
744
745 int AbstractMetaBuilder::figureOutEnumValue(const QString &stringValue,
745 int AbstractMetaBuilder::figureOutEnumValue(const QString &stringValue,
746 int oldValuevalue,
746 int oldValuevalue,
747 AbstractMetaEnum *meta_enum,
747 AbstractMetaEnum *meta_enum,
748 AbstractMetaFunction *meta_function)
748 AbstractMetaFunction *meta_function)
749 {
749 {
750 if (stringValue.isEmpty())
750 if (stringValue.isEmpty())
751 return oldValuevalue;
751 return oldValuevalue;
752
752
753 QStringList stringValues = stringValue.split("|");
753 QStringList stringValues = stringValue.split("|");
754
754
755 int returnValue = 0;
755 int returnValue = 0;
756
756
757 bool matched = false;
757 bool matched = false;
758
758
759 for (int i=0; i<stringValues.size(); ++i) {
759 for (int i=0; i<stringValues.size(); ++i) {
760 QString s = stringValues.at(i).trimmed();
760 QString s = stringValues.at(i).trimmed();
761
761
762 bool ok;
762 bool ok;
763 int v;
763 int v;
764
764
765 Operator op = findOperator(&s);
765 Operator op = findOperator(&s);
766
766
767 if (s.length() > 0 && s.at(0) == QLatin1Char('0'))
767 if (s.length() > 0 && s.at(0) == QLatin1Char('0'))
768 v = s.toUInt(&ok, 0);
768 v = s.toUInt(&ok, 0);
769 else
769 else
770 v = s.toInt(&ok);
770 v = s.toInt(&ok);
771
771
772 if (ok) {
772 if (ok) {
773 matched = true;
773 matched = true;
774
774
775 } else if (m_enum_values.contains(s)) {
775 } else if (m_enum_values.contains(s)) {
776 v = m_enum_values[s]->value();
776 v = m_enum_values[s]->value();
777 matched = true;
777 matched = true;
778
778
779 } else {
779 } else {
780 AbstractMetaEnumValue *ev = 0;
780 AbstractMetaEnumValue *ev = 0;
781
781
782 if (meta_enum && (ev = meta_enum->values().find(s))) {
782 if (meta_enum && (ev = meta_enum->values().find(s))) {
783 v = ev->value();
783 v = ev->value();
784 matched = true;
784 matched = true;
785
785
786 } else if (meta_enum && (ev = meta_enum->enclosingClass()->findEnumValue(s, meta_enum))) {
786 } else if (meta_enum && (ev = meta_enum->enclosingClass()->findEnumValue(s, meta_enum))) {
787 v = ev->value();
787 v = ev->value();
788 matched = true;
788 matched = true;
789
789
790 } else {
790 } else {
791 if (meta_enum)
791 if (meta_enum)
792 ReportHandler::warning("unhandled enum value: " + s + " in "
792 ReportHandler::warning("unhandled enum value: " + s + " in "
793 + meta_enum->enclosingClass()->name() + "::"
793 + meta_enum->enclosingClass()->name() + "::"
794 + meta_enum->name());
794 + meta_enum->name());
795 else
795 else
796 ReportHandler::warning("unhandled enum value: Unknown enum");
796 ReportHandler::warning("unhandled enum value: Unknown enum");
797 }
797 }
798 }
798 }
799
799
800 if (matched)
800 if (matched)
801 returnValue |= op.calculate(v);
801 returnValue |= op.calculate(v);
802 }
802 }
803
803
804 if (!matched) {
804 if (!matched) {
805 QString warn = QString("unmatched enum %1").arg(stringValue);
805 QString warn = QString("unmatched enum %1").arg(stringValue);
806
806
807 if (meta_function != 0) {
807 if (meta_function != 0) {
808 warn += QString(" when parsing default value of '%1' in class '%2'")
808 warn += QString(" when parsing default value of '%1' in class '%2'")
809 .arg(meta_function->name())
809 .arg(meta_function->name())
810 .arg(meta_function->implementingClass()->name());
810 .arg(meta_function->implementingClass()->name());
811 }
811 }
812
812
813 ReportHandler::warning(warn);
813 ReportHandler::warning(warn);
814 returnValue = oldValuevalue;
814 returnValue = oldValuevalue;
815 }
815 }
816
816
817 return returnValue;
817 return returnValue;
818 }
818 }
819
819
820 void AbstractMetaBuilder::figureOutEnumValuesForClass(AbstractMetaClass *meta_class,
820 void AbstractMetaBuilder::figureOutEnumValuesForClass(AbstractMetaClass *meta_class,
821 QSet<AbstractMetaClass *> *classes)
821 QSet<AbstractMetaClass *> *classes)
822 {
822 {
823 AbstractMetaClass *base = meta_class->baseClass();
823 AbstractMetaClass *base = meta_class->baseClass();
824
824
825 if (base != 0 && !classes->contains(base))
825 if (base != 0 && !classes->contains(base))
826 figureOutEnumValuesForClass(base, classes);
826 figureOutEnumValuesForClass(base, classes);
827
827
828 if (classes->contains(meta_class))
828 if (classes->contains(meta_class))
829 return;
829 return;
830
830
831 AbstractMetaEnumList enums = meta_class->enums();
831 AbstractMetaEnumList enums = meta_class->enums();
832 foreach (AbstractMetaEnum *e, enums) {
832 foreach (AbstractMetaEnum *e, enums) {
833 if (!e) {
833 if (!e) {
834 ReportHandler::warning("bad enum in class " + meta_class->name());
834 ReportHandler::warning("bad enum in class " + meta_class->name());
835 continue;
835 continue;
836 }
836 }
837 AbstractMetaEnumValueList lst = e->values();
837 AbstractMetaEnumValueList lst = e->values();
838 int value = 0;
838 int value = 0;
839 for (int i=0; i<lst.size(); ++i) {
839 for (int i=0; i<lst.size(); ++i) {
840 value = figureOutEnumValue(lst.at(i)->stringValue(), value, e);
840 value = figureOutEnumValue(lst.at(i)->stringValue(), value, e);
841 lst.at(i)->setValue(value);
841 lst.at(i)->setValue(value);
842 value++;
842 value++;
843 }
843 }
844
844
845 // Check for duplicate values...
845 // Check for duplicate values...
846 EnumTypeEntry *ete = e->typeEntry();
846 EnumTypeEntry *ete = e->typeEntry();
847 if (!ete->forceInteger()) {
847 if (!ete->forceInteger()) {
848 QHash<int, AbstractMetaEnumValue *> entries;
848 QHash<int, AbstractMetaEnumValue *> entries;
849 foreach (AbstractMetaEnumValue *v, lst) {
849 foreach (AbstractMetaEnumValue *v, lst) {
850
850
851 bool vRejected = ete->isEnumValueRejected(v->name());
851 bool vRejected = ete->isEnumValueRejected(v->name());
852
852
853 AbstractMetaEnumValue *current = entries.value(v->value());
853 AbstractMetaEnumValue *current = entries.value(v->value());
854 if (current) {
854 if (current) {
855 bool currentRejected = ete->isEnumValueRejected(current->name());
855 bool currentRejected = ete->isEnumValueRejected(current->name());
856 if (!currentRejected && !vRejected) {
856 if (!currentRejected && !vRejected) {
857 ReportHandler::warning(
857 ReportHandler::warning(
858 QString("duplicate enum values: %1::%2, %3 and %4 are %5, already rejected: (%6)")
858 QString("duplicate enum values: %1::%2, %3 and %4 are %5, already rejected: (%6)")
859 .arg(meta_class->name())
859 .arg(meta_class->name())
860 .arg(e->name())
860 .arg(e->name())
861 .arg(v->name())
861 .arg(v->name())
862 .arg(entries[v->value()]->name())
862 .arg(entries[v->value()]->name())
863 .arg(v->value())
863 .arg(v->value())
864 .arg(ete->enumValueRejections().join(", ")));
864 .arg(ete->enumValueRejections().join(", ")));
865 continue;
865 continue;
866 }
866 }
867 }
867 }
868
868
869 if (!vRejected)
869 if (!vRejected)
870 entries[v->value()] = v;
870 entries[v->value()] = v;
871 }
871 }
872
872
873 // Entries now contain all the original entries, no
873 // Entries now contain all the original entries, no
874 // rejected ones... Use this to generate the enumValueRedirection table.
874 // rejected ones... Use this to generate the enumValueRedirection table.
875 foreach (AbstractMetaEnumValue *reject, lst) {
875 foreach (AbstractMetaEnumValue *reject, lst) {
876 if (!ete->isEnumValueRejected(reject->name()))
876 if (!ete->isEnumValueRejected(reject->name()))
877 continue;
877 continue;
878
878
879 AbstractMetaEnumValue *used = entries.value(reject->value());
879 AbstractMetaEnumValue *used = entries.value(reject->value());
880 if (!used) {
880 if (!used) {
881 ReportHandler::warning(
881 ReportHandler::warning(
882 QString::fromLatin1("Rejected enum has no alternative...: %1::%2")
882 QString::fromLatin1("Rejected enum has no alternative...: %1::%2")
883 .arg(meta_class->name())
883 .arg(meta_class->name())
884 .arg(reject->name()));
884 .arg(reject->name()));
885 continue;
885 continue;
886 }
886 }
887 ete->addEnumValueRedirection(reject->name(), used->name());
887 ete->addEnumValueRedirection(reject->name(), used->name());
888 }
888 }
889
889
890 }
890 }
891 }
891 }
892
892
893
893
894
894
895 *classes += meta_class;
895 *classes += meta_class;
896 }
896 }
897
897
898
898
899 void AbstractMetaBuilder::figureOutEnumValues()
899 void AbstractMetaBuilder::figureOutEnumValues()
900 {
900 {
901 // Keep a set of classes that we already traversed. We use this to
901 // Keep a set of classes that we already traversed. We use this to
902 // enforce that we traverse base classes prior to subclasses.
902 // enforce that we traverse base classes prior to subclasses.
903 QSet<AbstractMetaClass *> classes;
903 QSet<AbstractMetaClass *> classes;
904 foreach (AbstractMetaClass *c, m_meta_classes) {
904 foreach (AbstractMetaClass *c, m_meta_classes) {
905 figureOutEnumValuesForClass(c, &classes);
905 figureOutEnumValuesForClass(c, &classes);
906 }
906 }
907 }
907 }
908
908
909 void AbstractMetaBuilder::figureOutDefaultEnumArguments()
909 void AbstractMetaBuilder::figureOutDefaultEnumArguments()
910 {
910 {
911 foreach (AbstractMetaClass *meta_class, m_meta_classes) {
911 foreach (AbstractMetaClass *meta_class, m_meta_classes) {
912 foreach (AbstractMetaFunction *meta_function, meta_class->functions()) {
912 foreach (AbstractMetaFunction *meta_function, meta_class->functions()) {
913 foreach (AbstractMetaArgument *arg, meta_function->arguments()) {
913 foreach (AbstractMetaArgument *arg, meta_function->arguments()) {
914
914
915 QString expr = arg->defaultValueExpression();
915 QString expr = arg->defaultValueExpression();
916 if (expr.isEmpty())
916 if (expr.isEmpty())
917 continue;
917 continue;
918
918
919 if (!meta_function->replacedDefaultExpression(meta_function->implementingClass(),
919 if (!meta_function->replacedDefaultExpression(meta_function->implementingClass(),
920 arg->argumentIndex()+1).isEmpty()) {
920 arg->argumentIndex()+1).isEmpty()) {
921 continue;
921 continue;
922 }
922 }
923
923
924 QString new_expr = expr;
924 QString new_expr = expr;
925 if (arg->type()->isEnum()) {
925 if (arg->type()->isEnum()) {
926 QStringList lst = expr.split(QLatin1String("::"));
926 QStringList lst = expr.split(QLatin1String("::"));
927 if (lst.size() == 1) {
927 if (lst.size() == 1) {
928 QVector<AbstractMetaClass *> classes(1, meta_class);
928 QVector<AbstractMetaClass *> classes(1, meta_class);
929 AbstractMetaEnum *e = 0;
929 AbstractMetaEnum *e = 0;
930 while (!classes.isEmpty() && e == 0) {
930 while (!classes.isEmpty() && e == 0) {
931 if (classes.front() != 0) {
931 if (classes.front() != 0) {
932 classes << classes.front()->baseClass();
932 classes << classes.front()->baseClass();
933
933
934 AbstractMetaClassList interfaces = classes.front()->interfaces();
934 AbstractMetaClassList interfaces = classes.front()->interfaces();
935 foreach (AbstractMetaClass *interface, interfaces)
935 foreach (AbstractMetaClass *interface, interfaces)
936 classes << interface->primaryInterfaceImplementor();
936 classes << interface->primaryInterfaceImplementor();
937
937
938 e = classes.front()->findEnumForValue(expr);
938 e = classes.front()->findEnumForValue(expr);
939 }
939 }
940
940
941 classes.pop_front();
941 classes.pop_front();
942 }
942 }
943
943
944 if (e != 0) {
944 if (e != 0) {
945 new_expr = QString("%1.%2")
945 new_expr = QString("%1.%2")
946 .arg(e->typeEntry()->qualifiedTargetLangName())
946 .arg(e->typeEntry()->qualifiedTargetLangName())
947 .arg(expr);
947 .arg(expr);
948 } else {
948 } else {
949 ReportHandler::warning("Cannot find enum constant for value '" + expr + "' in '" + meta_class->name() + "' or any of its super classes");
949 ReportHandler::warning("Cannot find enum constant for value '" + expr + "' in '" + meta_class->name() + "' or any of its super classes");
950 }
950 }
951 } else if (lst.size() == 2) {
951 } else if (lst.size() == 2) {
952 AbstractMetaClass *cl = m_meta_classes.findClass(lst.at(0));
952 AbstractMetaClass *cl = m_meta_classes.findClass(lst.at(0));
953 if (!cl) {
953 if (!cl) {
954 ReportHandler::warning("missing required class for enums: " + lst.at(0));
954 ReportHandler::warning("missing required class for enums: " + lst.at(0));
955 continue;
955 continue;
956 }
956 }
957 new_expr = QString("%1.%2.%3")
957 new_expr = QString("%1.%2.%3")
958 .arg(cl->typeEntry()->qualifiedTargetLangName())
958 .arg(cl->typeEntry()->qualifiedTargetLangName())
959 .arg(arg->type()->name())
959 .arg(arg->type()->name())
960 .arg(lst.at(1));
960 .arg(lst.at(1));
961 } else {
961 } else {
962 ReportHandler::warning("bad default value passed to enum " + expr);
962 ReportHandler::warning("bad default value passed to enum " + expr);
963 }
963 }
964
964
965 } else if(arg->type()->isFlags()) {
965 } else if(arg->type()->isFlags()) {
966 const FlagsTypeEntry *flagsEntry =
966 const FlagsTypeEntry *flagsEntry =
967 static_cast<const FlagsTypeEntry *>(arg->type()->typeEntry());
967 static_cast<const FlagsTypeEntry *>(arg->type()->typeEntry());
968 EnumTypeEntry *enumEntry = flagsEntry->originator();
968 EnumTypeEntry *enumEntry = flagsEntry->originator();
969 AbstractMetaEnum *meta_enum = m_meta_classes.findEnum(enumEntry);
969 AbstractMetaEnum *meta_enum = m_meta_classes.findEnum(enumEntry);
970 if (!meta_enum) {
970 if (!meta_enum) {
971 ReportHandler::warning("unknown required enum " + enumEntry->qualifiedCppName());
971 ReportHandler::warning("unknown required enum " + enumEntry->qualifiedCppName());
972 continue;
972 continue;
973 }
973 }
974
974
975 int value = figureOutEnumValue(expr, 0, meta_enum, meta_function);
975 int value = figureOutEnumValue(expr, 0, meta_enum, meta_function);
976 new_expr = QString::number(value);
976 new_expr = QString::number(value);
977
977
978 } else if (arg->type()->isPrimitive()) {
978 } else if (arg->type()->isPrimitive()) {
979 AbstractMetaEnumValue *value = 0;
979 AbstractMetaEnumValue *value = 0;
980 if (expr.contains("::"))
980 if (expr.contains("::"))
981 value = m_meta_classes.findEnumValue(expr);
981 value = m_meta_classes.findEnumValue(expr);
982 if (!value)
982 if (!value)
983 value = meta_class->findEnumValue(expr, 0);
983 value = meta_class->findEnumValue(expr, 0);
984
984
985 if (value) {
985 if (value) {
986 new_expr = QString::number(value->value());
986 new_expr = QString::number(value->value());
987 } else if (expr.contains(QLatin1Char('+'))) {
987 } else if (expr.contains(QLatin1Char('+'))) {
988 new_expr = QString::number(figureOutEnumValue(expr, 0, 0));
988 new_expr = QString::number(figureOutEnumValue(expr, 0, 0));
989
989
990 }
990 }
991
991
992
992
993
993
994 }
994 }
995
995
996 arg->setDefaultValueExpression(new_expr);
996 arg->setDefaultValueExpression(new_expr);
997 }
997 }
998 }
998 }
999 }
999 }
1000 }
1000 }
1001
1001
1002
1002
1003 AbstractMetaEnum *AbstractMetaBuilder::traverseEnum(EnumModelItem enum_item, AbstractMetaClass *enclosing, const QSet<QString> &enumsDeclarations)
1003 AbstractMetaEnum *AbstractMetaBuilder::traverseEnum(EnumModelItem enum_item, AbstractMetaClass *enclosing, const QSet<QString> &enumsDeclarations)
1004 {
1004 {
1005 // Skipping private enums.
1005 // Skipping private enums.
1006 if (enum_item->accessPolicy() == CodeModel::Private) {
1006 if (enum_item->accessPolicy() == CodeModel::Private) {
1007 return 0;
1007 return 0;
1008 }
1008 }
1009
1009
1010 QString qualified_name = enum_item->qualifiedName().join("::");
1010 QString qualified_name = enum_item->qualifiedName().join("::");
1011
1011
1012 TypeEntry *type_entry = TypeDatabase::instance()->findType(qualified_name);
1012 TypeEntry *type_entry = TypeDatabase::instance()->findType(qualified_name);
1013 QString enum_name = enum_item->name();
1013 QString enum_name = enum_item->name();
1014
1014
1015 QString class_name;
1015 QString class_name;
1016 if (m_current_class)
1016 if (m_current_class)
1017 class_name = m_current_class->typeEntry()->qualifiedCppName();
1017 class_name = m_current_class->typeEntry()->qualifiedCppName();
1018
1018
1019 if (TypeDatabase::instance()->isEnumRejected(class_name, enum_name)) {
1019 if (TypeDatabase::instance()->isEnumRejected(class_name, enum_name)) {
1020 m_rejected_enums.insert(qualified_name, GenerationDisabled);
1020 m_rejected_enums.insert(qualified_name, GenerationDisabled);
1021 return 0;
1021 return 0;
1022 }
1022 }
1023
1023
1024 if (!type_entry || !type_entry->isEnum()) {
1024 if (!type_entry || !type_entry->isEnum()) {
1025 QString context = m_current_class ? m_current_class->name() : QLatin1String("");
1025 QString context = m_current_class ? m_current_class->name() : QLatin1String("");
1026 ReportHandler::warning(QString("enum '%1' does not have a type entry or is not an enum")
1026 ReportHandler::warning(QString("enum '%1' does not have a type entry or is not an enum")
1027 .arg(qualified_name));
1027 .arg(qualified_name));
1028 m_rejected_enums.insert(qualified_name, NotInTypeSystem);
1028 m_rejected_enums.insert(qualified_name, NotInTypeSystem);
1029 return 0;
1029 return 0;
1030 }
1030 }
1031
1031
1032 AbstractMetaEnum *meta_enum = createMetaEnum();
1032 AbstractMetaEnum *meta_enum = createMetaEnum();
1033 if ( enumsDeclarations.contains(qualified_name)
1033 if ( enumsDeclarations.contains(qualified_name)
1034 || enumsDeclarations.contains(enum_name)) {
1034 || enumsDeclarations.contains(enum_name)) {
1035 meta_enum->setHasQEnumsDeclaration(true);
1035 meta_enum->setHasQEnumsDeclaration(true);
1036 }
1036 }
1037
1037
1038 meta_enum->setTypeEntry((EnumTypeEntry *) type_entry);
1038 meta_enum->setTypeEntry((EnumTypeEntry *) type_entry);
1039 switch (enum_item->accessPolicy()) {
1039 switch (enum_item->accessPolicy()) {
1040 case CodeModel::Public: *meta_enum += AbstractMetaAttributes::Public; break;
1040 case CodeModel::Public: *meta_enum += AbstractMetaAttributes::Public; break;
1041 case CodeModel::Protected: *meta_enum += AbstractMetaAttributes::Protected; break;
1041 case CodeModel::Protected: *meta_enum += AbstractMetaAttributes::Protected; break;
1042 // case CodeModel::Private: *meta_enum += AbstractMetaAttributes::Private; break;
1042 // case CodeModel::Private: *meta_enum += AbstractMetaAttributes::Private; break;
1043 default: break;
1043 default: break;
1044 }
1044 }
1045
1045
1046 ReportHandler::debugMedium(QString(" - traversing enum %1").arg(meta_enum->fullName()));
1046 ReportHandler::debugMedium(QString(" - traversing enum %1").arg(meta_enum->fullName()));
1047
1047
1048 foreach (EnumeratorModelItem value, enum_item->enumerators()) {
1048 foreach (EnumeratorModelItem value, enum_item->enumerators()) {
1049
1049
1050 AbstractMetaEnumValue *meta_enum_value = createMetaEnumValue();
1050 AbstractMetaEnumValue *meta_enum_value = createMetaEnumValue();
1051 meta_enum_value->setName(value->name());
1051 meta_enum_value->setName(value->name());
1052 // Deciding the enum value...
1052 // Deciding the enum value...
1053
1053
1054 meta_enum_value->setStringValue(value->value());
1054 meta_enum_value->setStringValue(value->value());
1055 meta_enum->addEnumValue(meta_enum_value);
1055 meta_enum->addEnumValue(meta_enum_value);
1056
1056
1057 ReportHandler::debugFull(" - " + meta_enum_value->name() + " = "
1057 ReportHandler::debugFull(" - " + meta_enum_value->name() + " = "
1058 + meta_enum_value->value());
1058 + meta_enum_value->value());
1059
1059
1060 // Add into global register...
1060 // Add into global register...
1061 if (enclosing)
1061 if (enclosing)
1062 m_enum_values[enclosing->name() + "::" + meta_enum_value->name()] = meta_enum_value;
1062 m_enum_values[enclosing->name() + "::" + meta_enum_value->name()] = meta_enum_value;
1063 else
1063 else
1064 m_enum_values[meta_enum_value->name()] = meta_enum_value;
1064 m_enum_values[meta_enum_value->name()] = meta_enum_value;
1065 }
1065 }
1066
1066
1067 QFileInfo info(enum_item->fileName());
1067 QFileInfo info(enum_item->fileName());
1068 meta_enum->typeEntry()->setInclude(Include(Include::IncludePath, info.fileName()));
1068 meta_enum->typeEntry()->setInclude(Include(Include::IncludePath, info.fileName()));
1069
1069
1070 m_enums << meta_enum;
1070 m_enums << meta_enum;
1071
1071
1072 return meta_enum;
1072 return meta_enum;
1073 }
1073 }
1074
1074
1075 AbstractMetaClass *AbstractMetaBuilder::traverseTypeAlias(TypeAliasModelItem typeAlias)
1075 AbstractMetaClass *AbstractMetaBuilder::traverseTypeAlias(TypeAliasModelItem typeAlias)
1076 {
1076 {
1077 QString class_name = strip_template_args(typeAlias->name());
1077 QString class_name = strip_template_args(typeAlias->name());
1078
1078
1079 QString full_class_name = class_name;
1079 QString full_class_name = class_name;
1080 // we have an inner class
1080 // we have an inner class
1081 if (m_current_class) {
1081 if (m_current_class) {
1082 full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
1082 full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
1083 + "::" + full_class_name;
1083 + "::" + full_class_name;
1084 }
1084 }
1085
1085
1086 // If we haven't specified anything for the typedef, then we don't care
1086 // If we haven't specified anything for the typedef, then we don't care
1087 ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
1087 ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
1088 if (type == 0)
1088 if (type == 0)
1089 return 0;
1089 return 0;
1090
1090
1091 if (type->isObject())
1091 if (type->isObject())
1092 static_cast<ObjectTypeEntry *>(type)->setQObject(isQObject(strip_template_args(typeAlias->type().qualifiedName().join("::"))));
1092 static_cast<ObjectTypeEntry *>(type)->setQObject(isQObject(strip_template_args(typeAlias->type().qualifiedName().join("::"))));
1093
1093
1094 AbstractMetaClass *meta_class = createMetaClass();
1094 AbstractMetaClass *meta_class = createMetaClass();
1095 meta_class->setTypeAlias(true);
1095 meta_class->setTypeAlias(true);
1096 meta_class->setTypeEntry(type);
1096 meta_class->setTypeEntry(type);
1097 meta_class->setBaseClassNames(QStringList() << typeAlias->type().qualifiedName().join("::"));
1097 meta_class->setBaseClassNames(QStringList() << typeAlias->type().qualifiedName().join("::"));
1098 *meta_class += AbstractMetaAttributes::Public;
1098 *meta_class += AbstractMetaAttributes::Public;
1099
1099
1100 // Set the default include file name
1100 // Set the default include file name
1101 if (!type->include().isValid()) {
1101 if (!type->include().isValid()) {
1102 QFileInfo info(typeAlias->fileName());
1102 QFileInfo info(typeAlias->fileName());
1103 type->setInclude(Include(Include::IncludePath, info.fileName()));
1103 type->setInclude(Include(Include::IncludePath, info.fileName()));
1104 }
1104 }
1105
1105
1106 return meta_class;
1106 return meta_class;
1107 }
1107 }
1108
1108
1109 AbstractMetaClass *AbstractMetaBuilder::traverseClass(ClassModelItem class_item)
1109 AbstractMetaClass *AbstractMetaBuilder::traverseClass(ClassModelItem class_item)
1110 {
1110 {
1111 QString class_name = strip_template_args(class_item->name());
1111 QString class_name = strip_template_args(class_item->name());
1112 QString full_class_name = class_name;
1112 QString full_class_name = class_name;
1113
1113
1114 // we have inner an class
1114 // we have inner an class
1115 if (m_current_class) {
1115 if (m_current_class) {
1116 full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
1116 full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
1117 + "::" + full_class_name;
1117 + "::" + full_class_name;
1118 }
1118 }
1119
1119
1120 ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
1120 ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
1121 RejectReason reason = NoReason;
1121 RejectReason reason = NoReason;
1122
1122
1123 if (full_class_name == "QMetaTypeId") {
1123 if (full_class_name == "QMetaTypeId") {
1124 // QtScript: record which types have been declared
1124 // QtScript: record which types have been declared
1125 int lpos = class_item->name().indexOf('<');
1125 int lpos = class_item->name().indexOf('<');
1126 int rpos = class_item->name().lastIndexOf('>');
1126 int rpos = class_item->name().lastIndexOf('>');
1127 if ((lpos != -1) && (rpos != -1)) {
1127 if ((lpos != -1) && (rpos != -1)) {
1128 QString declared_typename = class_item->name().mid(lpos+1, rpos - lpos-1);
1128 QString declared_typename = class_item->name().mid(lpos+1, rpos - lpos-1);
1129 m_qmetatype_declared_typenames.insert(declared_typename);
1129 m_qmetatype_declared_typenames.insert(declared_typename);
1130 }
1130 }
1131 }
1131 }
1132
1132
1133 if (TypeDatabase::instance()->isClassRejected(full_class_name)) {
1133 if (TypeDatabase::instance()->isClassRejected(full_class_name)) {
1134 reason = GenerationDisabled;
1134 reason = GenerationDisabled;
1135 } else if (!type) {
1135 } else if (!type) {
1136 TypeEntry *te = TypeDatabase::instance()->findType(full_class_name);
1136 TypeEntry *te = TypeDatabase::instance()->findType(full_class_name);
1137 if (te && !te->isComplex())
1137 if (te && !te->isComplex())
1138 reason = RedefinedToNotClass;
1138 reason = RedefinedToNotClass;
1139 else
1139 else
1140 reason = NotInTypeSystem;
1140 reason = NotInTypeSystem;
1141 } else if (type->codeGeneration() == TypeEntry::GenerateNothing) {
1141 } else if (type->codeGeneration() == TypeEntry::GenerateNothing) {
1142 reason = GenerationDisabled;
1142 reason = GenerationDisabled;
1143 }
1143 }
1144
1144
1145 if (reason != NoReason) {
1145 if (reason != NoReason) {
1146 m_rejected_classes.insert(full_class_name, reason);
1146 m_rejected_classes.insert(full_class_name, reason);
1147 return 0;
1147 return 0;
1148 }
1148 }
1149
1149
1150 if (type->isObject()) {
1150 if (type->isObject()) {
1151 ((ObjectTypeEntry *)type)->setQObject(isQObject(full_class_name));
1151 ((ObjectTypeEntry *)type)->setQObject(isQObject(full_class_name));
1152 }
1152 }
1153
1153
1154 AbstractMetaClass *meta_class = createMetaClass();
1154 AbstractMetaClass *meta_class = createMetaClass();
1155 meta_class->setTypeEntry(type);
1155 meta_class->setTypeEntry(type);
1156 meta_class->setBaseClassNames(class_item->baseClasses());
1156 meta_class->setBaseClassNames(class_item->baseClasses());
1157 *meta_class += AbstractMetaAttributes::Public;
1157 *meta_class += AbstractMetaAttributes::Public;
1158
1158
1159 AbstractMetaClass *old_current_class = m_current_class;
1159 AbstractMetaClass *old_current_class = m_current_class;
1160 m_current_class = meta_class;
1160 m_current_class = meta_class;
1161
1161
1162 if (type->isContainer()) {
1162 if (type->isContainer()) {
1163 ReportHandler::debugSparse(QString("container: '%1'").arg(full_class_name));
1163 ReportHandler::debugSparse(QString("container: '%1'").arg(full_class_name));
1164 } else {
1164 } else {
1165 ReportHandler::debugSparse(QString("class: '%1'").arg(meta_class->fullName()));
1165 ReportHandler::debugSparse(QString("class: '%1'").arg(meta_class->fullName()));
1166 }
1166 }
1167
1167
1168 TemplateParameterList template_parameters = class_item->templateParameters();
1168 TemplateParameterList template_parameters = class_item->templateParameters();
1169 QList<TypeEntry *> template_args;
1169 QList<TypeEntry *> template_args;
1170 template_args.clear();
1170 template_args.clear();
1171 for (int i=0; i<template_parameters.size(); ++i) {
1171 for (int i=0; i<template_parameters.size(); ++i) {
1172 const TemplateParameterModelItem &param = template_parameters.at(i);
1172 const TemplateParameterModelItem &param = template_parameters.at(i);
1173 TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name());
1173 TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name());
1174 param_type->setOrdinal(i);
1174 param_type->setOrdinal(i);
1175 template_args.append(param_type);
1175 template_args.append(param_type);
1176 }
1176 }
1177 meta_class->setTemplateArguments(template_args);
1177 meta_class->setTemplateArguments(template_args);
1178
1178
1179 parseQ_Property(meta_class, class_item->propertyDeclarations());
1179 parseQ_Property(meta_class, class_item->propertyDeclarations());
1180
1180
1181 traverseFunctions(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
1181 traverseFunctions(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
1182 traverseEnums(model_dynamic_cast<ScopeModelItem>(class_item), meta_class, class_item->enumsDeclarations());
1182 traverseEnums(model_dynamic_cast<ScopeModelItem>(class_item), meta_class, class_item->enumsDeclarations());
1183 traverseFields(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
1183 traverseFields(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
1184
1184
1185 // Inner classes
1185 // Inner classes
1186 {
1186 {
1187 QList<ClassModelItem> inner_classes = class_item->classMap().values();
1187 QList<ClassModelItem> inner_classes = class_item->classMap().values();
1188 foreach (const ClassModelItem &ci, inner_classes) {
1188 foreach (const ClassModelItem &ci, inner_classes) {
1189 AbstractMetaClass *cl = traverseClass(ci);
1189 AbstractMetaClass *cl = traverseClass(ci);
1190 if (cl) {
1190 if (cl) {
1191 cl->setEnclosingClass(meta_class);
1191 cl->setEnclosingClass(meta_class);
1192 m_meta_classes << cl;
1192 m_meta_classes << cl;
1193 }
1193 }
1194 }
1194 }
1195
1195
1196 }
1196 }
1197
1197
1198 // Go through all typedefs to see if we have defined any
1198 // Go through all typedefs to see if we have defined any
1199 // specific typedefs to be used as classes.
1199 // specific typedefs to be used as classes.
1200 TypeAliasList typeAliases = class_item->typeAliases();
1200 TypeAliasList typeAliases = class_item->typeAliases();
1201 foreach (TypeAliasModelItem typeAlias, typeAliases) {
1201 foreach (TypeAliasModelItem typeAlias, typeAliases) {
1202 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
1202 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
1203 if (cls != 0) {
1203 if (cls != 0) {
1204 cls->setEnclosingClass(meta_class);
1204 cls->setEnclosingClass(meta_class);
1205 addAbstractMetaClass(cls);
1205 addAbstractMetaClass(cls);
1206 }
1206 }
1207 }
1207 }
1208
1208
1209
1209
1210 m_current_class = old_current_class;
1210 m_current_class = old_current_class;
1211
1211
1212 // Set the default include file name
1212 // Set the default include file name
1213 if (!type->include().isValid()) {
1213 if (!type->include().isValid()) {
1214 QFileInfo info(class_item->fileName());
1214 QFileInfo info(class_item->fileName());
1215 type->setInclude(Include(Include::IncludePath, info.fileName()));
1215 type->setInclude(Include(Include::IncludePath, info.fileName()));
1216 }
1216 }
1217
1217
1218 return meta_class;
1218 return meta_class;
1219 }
1219 }
1220
1220
1221 AbstractMetaField *AbstractMetaBuilder::traverseField(VariableModelItem field, const AbstractMetaClass *cls)
1221 AbstractMetaField *AbstractMetaBuilder::traverseField(VariableModelItem field, const AbstractMetaClass *cls)
1222 {
1222 {
1223 QString field_name = field->name();
1223 QString field_name = field->name();
1224 QString class_name = m_current_class->typeEntry()->qualifiedCppName();
1224 QString class_name = m_current_class->typeEntry()->qualifiedCppName();
1225
1225
1226 // Ignore friend decl.
1226 // Ignore friend decl.
1227 if (field->isFriend())
1227 if (field->isFriend())
1228 return 0;
1228 return 0;
1229
1229
1230 if (field->accessPolicy() == CodeModel::Private)
1230 if (field->accessPolicy() == CodeModel::Private)
1231 return 0;
1231 return 0;
1232
1232
1233 if (TypeDatabase::instance()->isFieldRejected(class_name, field_name)) {
1233 if (TypeDatabase::instance()->isFieldRejected(class_name, field_name)) {
1234 m_rejected_fields.insert(class_name + "::" + field_name, GenerationDisabled);
1234 m_rejected_fields.insert(class_name + "::" + field_name, GenerationDisabled);
1235 return 0;
1235 return 0;
1236 }
1236 }
1237
1237
1238
1238
1239 AbstractMetaField *meta_field = createMetaField();
1239 AbstractMetaField *meta_field = createMetaField();
1240 meta_field->setName(field_name);
1240 meta_field->setName(field_name);
1241 meta_field->setEnclosingClass(cls);
1241 meta_field->setEnclosingClass(cls);
1242
1242
1243 bool ok;
1243 bool ok;
1244 TypeInfo field_type = field->type();
1244 TypeInfo field_type = field->type();
1245 AbstractMetaType *meta_type = translateType(field_type, &ok);
1245 AbstractMetaType *meta_type = translateType(field_type, &ok);
1246
1246
1247 if (!meta_type || !ok) {
1247 if (!meta_type || !ok) {
1248 ReportHandler::warning(QString("skipping field '%1::%2' with unmatched type '%3'")
1248 ReportHandler::warning(QString("skipping field '%1::%2' with unmatched type '%3'")
1249 .arg(m_current_class->name())
1249 .arg(m_current_class->name())
1250 .arg(field_name)
1250 .arg(field_name)
1251 .arg(TypeInfo::resolveType(field_type, currentScope()->toItem()).qualifiedName().join("::")));
1251 .arg(TypeInfo::resolveType(field_type, currentScope()->toItem()).qualifiedName().join("::")));
1252 delete meta_field;
1252 delete meta_field;
1253 return 0;
1253 return 0;
1254 }
1254 }
1255
1255
1256 meta_field->setType(meta_type);
1256 meta_field->setType(meta_type);
1257
1257
1258 uint attr = 0;
1258 uint attr = 0;
1259 if (field->isStatic())
1259 if (field->isStatic())
1260 attr |= AbstractMetaAttributes::Static;
1260 attr |= AbstractMetaAttributes::Static;
1261
1261
1262 CodeModel::AccessPolicy policy = field->accessPolicy();
1262 CodeModel::AccessPolicy policy = field->accessPolicy();
1263 if (policy == CodeModel::Public)
1263 if (policy == CodeModel::Public)
1264 attr |= AbstractMetaAttributes::Public;
1264 attr |= AbstractMetaAttributes::Public;
1265 else if (policy == CodeModel::Protected)
1265 else if (policy == CodeModel::Protected)
1266 attr |= AbstractMetaAttributes::Protected;
1266 attr |= AbstractMetaAttributes::Protected;
1267 else
1267 else
1268 attr |= AbstractMetaAttributes::Private;
1268 attr |= AbstractMetaAttributes::Private;
1269 meta_field->setAttributes(attr);
1269 meta_field->setAttributes(attr);
1270
1270
1271 return meta_field;
1271 return meta_field;
1272 }
1272 }
1273
1273
1274 void AbstractMetaBuilder::traverseFields(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
1274 void AbstractMetaBuilder::traverseFields(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
1275 {
1275 {
1276 foreach (VariableModelItem field, scope_item->variables()) {
1276 foreach (VariableModelItem field, scope_item->variables()) {
1277 AbstractMetaField *meta_field = traverseField(field, meta_class);
1277 AbstractMetaField *meta_field = traverseField(field, meta_class);
1278
1278
1279 if (meta_field) {
1279 if (meta_field) {
1280 meta_field->setOriginalAttributes(meta_field->attributes());
1280 meta_field->setOriginalAttributes(meta_field->attributes());
1281 meta_class->addField(meta_field);
1281 meta_class->addField(meta_field);
1282 }
1282 }
1283 }
1283 }
1284 }
1284 }
1285
1285
1286 void AbstractMetaBuilder::setupFunctionDefaults(AbstractMetaFunction *meta_function, AbstractMetaClass *meta_class)
1286 void AbstractMetaBuilder::setupFunctionDefaults(AbstractMetaFunction *meta_function, AbstractMetaClass *meta_class)
1287 {
1287 {
1288 // Set the default value of the declaring class. This may be changed
1288 // Set the default value of the declaring class. This may be changed
1289 // in fixFunctions later on
1289 // in fixFunctions later on
1290 meta_function->setDeclaringClass(meta_class);
1290 meta_function->setDeclaringClass(meta_class);
1291
1291
1292 // Some of the queries below depend on the implementing class being set
1292 // Some of the queries below depend on the implementing class being set
1293 // to function properly. Such as function modifications
1293 // to function properly. Such as function modifications
1294 meta_function->setImplementingClass(meta_class);
1294 meta_function->setImplementingClass(meta_class);
1295
1295
1296 if (meta_function->name() == "operator_equal")
1296 if (meta_function->name() == "operator_equal")
1297 meta_class->setHasEqualsOperator(true);
1297 meta_class->setHasEqualsOperator(true);
1298
1298
1299 if (!meta_function->isFinalInTargetLang()
1299 if (!meta_function->isFinalInTargetLang()
1300 && meta_function->isRemovedFrom(meta_class, TypeSystem::TargetLangCode)) {
1300 && meta_function->isRemovedFrom(meta_class, TypeSystem::TargetLangCode)) {
1301 *meta_function += AbstractMetaAttributes::FinalInCpp;
1301 *meta_function += AbstractMetaAttributes::FinalInCpp;
1302 }
1302 }
1303 }
1303 }
1304
1304
1305 void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
1305 void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
1306 {
1306 {
1307 foreach (FunctionModelItem function, scope_item->functions()) {
1307 foreach (FunctionModelItem function, scope_item->functions()) {
1308 AbstractMetaFunction *meta_function = traverseFunction(function);
1308 AbstractMetaFunction *meta_function = traverseFunction(function);
1309
1309
1310 if (meta_function) {
1310 if (meta_function) {
1311 meta_function->setOriginalAttributes(meta_function->attributes());
1311 meta_function->setOriginalAttributes(meta_function->attributes());
1312 if (meta_class->isNamespace())
1312 if (meta_class->isNamespace())
1313 *meta_function += AbstractMetaAttributes::Static;
1313 *meta_function += AbstractMetaAttributes::Static;
1314
1314
1315 if (QPropertySpec *read = meta_class->propertySpecForRead(meta_function->name())) {
1315 if (QPropertySpec *read = meta_class->propertySpecForRead(meta_function->name())) {
1316 if (read->type() == meta_function->type()->typeEntry()) {
1316 if (read->type() == meta_function->type()->typeEntry()) {
1317 *meta_function += AbstractMetaAttributes::PropertyReader;
1317 *meta_function += AbstractMetaAttributes::PropertyReader;
1318 meta_function->setPropertySpec(read);
1318 meta_function->setPropertySpec(read);
1319 // printf("%s is reader for %s\n",
1319 // printf("%s is reader for %s\n",
1320 // qPrintable(meta_function->name()),
1320 // qPrintable(meta_function->name()),
1321 // qPrintable(read->name()));
1321 // qPrintable(read->name()));
1322 }
1322 }
1323 } else if (QPropertySpec *write =
1323 } else if (QPropertySpec *write =
1324 meta_class->propertySpecForWrite(meta_function->name())) {
1324 meta_class->propertySpecForWrite(meta_function->name())) {
1325 if (write->type() == meta_function->arguments().at(0)->type()->typeEntry()) {
1325 if (write->type() == meta_function->arguments().at(0)->type()->typeEntry()) {
1326 *meta_function += AbstractMetaAttributes::PropertyWriter;
1326 *meta_function += AbstractMetaAttributes::PropertyWriter;
1327 meta_function->setPropertySpec(write);
1327 meta_function->setPropertySpec(write);
1328 // printf("%s is writer for %s\n",
1328 // printf("%s is writer for %s\n",
1329 // qPrintable(meta_function->name()),
1329 // qPrintable(meta_function->name()),
1330 // qPrintable(write->name()));
1330 // qPrintable(write->name()));
1331 }
1331 }
1332 } else if (QPropertySpec *reset =
1332 } else if (QPropertySpec *reset =
1333 meta_class->propertySpecForReset(meta_function->name())) {
1333 meta_class->propertySpecForReset(meta_function->name())) {
1334 *meta_function += AbstractMetaAttributes::PropertyResetter;
1334 *meta_function += AbstractMetaAttributes::PropertyResetter;
1335 meta_function->setPropertySpec(reset);
1335 meta_function->setPropertySpec(reset);
1336 // printf("%s is resetter for %s\n",
1336 // printf("%s is resetter for %s\n",
1337 // qPrintable(meta_function->name()),
1337 // qPrintable(meta_function->name()),
1338 // qPrintable(reset->name()));
1338 // qPrintable(reset->name()));
1339 }
1339 }
1340
1340
1341
1341
1342 bool isInvalidDestructor = meta_function->isDestructor() && meta_function->isPrivate();
1342 bool isInvalidDestructor = meta_function->isDestructor() && meta_function->isPrivate();
1343 bool isInvalidConstructor = meta_function->isConstructor()
1343 bool isInvalidConstructor = meta_function->isConstructor()
1344 && (meta_function->isPrivate() || meta_function->isInvalid());
1344 && (meta_function->isPrivate() || meta_function->isInvalid());
1345 if ((isInvalidDestructor || isInvalidConstructor)
1345 if ((isInvalidDestructor || isInvalidConstructor)
1346 && !meta_class->hasNonPrivateConstructor()) {
1346 && !meta_class->hasNonPrivateConstructor()) {
1347 *meta_class += AbstractMetaAttributes::Final;
1347 *meta_class += AbstractMetaAttributes::Final;
1348 } else if (meta_function->isConstructor() && !meta_function->isPrivate()) {
1348 } else if (meta_function->isConstructor() && !meta_function->isPrivate()) {
1349 *meta_class -= AbstractMetaAttributes::Final;
1349 *meta_class -= AbstractMetaAttributes::Final;
1350 meta_class->setHasNonPrivateConstructor(true);
1350 meta_class->setHasNonPrivateConstructor(true);
1351 }
1351 }
1352
1352
1353 // Classes with virtual destructors should always have a shell class
1353 // Classes with virtual destructors should always have a shell class
1354 // (since we aren't registering the destructors, we need this extra check)
1354 // (since we aren't registering the destructors, we need this extra check)
1355 if (meta_function->isDestructor() && !meta_function->isFinal())
1355 if (meta_function->isDestructor() && !meta_function->isFinal())
1356 meta_class->setForceShellClass(true);
1356 meta_class->setForceShellClass(true);
1357
1357
1358 if (!meta_function->isDestructor()
1358 if (!meta_function->isDestructor()
1359 && !meta_function->isInvalid()
1359 && !meta_function->isInvalid()
1360 && (!meta_function->isConstructor() || !meta_function->isPrivate())) {
1360 && (!meta_function->isConstructor() || !meta_function->isPrivate())) {
1361
1361
1362 if (meta_class->typeEntry()->designatedInterface() && !meta_function->isPublic()
1362 if (meta_class->typeEntry()->designatedInterface() && !meta_function->isPublic()
1363 && !meta_function->isPrivate()) {
1363 && !meta_function->isPrivate()) {
1364 QString warn = QString("non-public function '%1' in interface '%2'")
1364 QString warn = QString("non-public function '%1' in interface '%2'")
1365 .arg(meta_function->name()).arg(meta_class->name());
1365 .arg(meta_function->name()).arg(meta_class->name());
1366 ReportHandler::warning(warn);
1366 ReportHandler::warning(warn);
1367
1367
1368 meta_function->setVisibility(AbstractMetaClass::Public);
1368 meta_function->setVisibility(AbstractMetaClass::Public);
1369 }
1369 }
1370
1370
1371 setupFunctionDefaults(meta_function, meta_class);
1371 setupFunctionDefaults(meta_function, meta_class);
1372
1372
1373 if (meta_function->isSignal() && meta_class->hasSignal(meta_function)) {
1373 if (meta_function->isSignal() && meta_class->hasSignal(meta_function)) {
1374 QString warn = QString("signal '%1' in class '%2' is overloaded.")
1374 QString warn = QString("signal '%1' in class '%2' is overloaded.")
1375 .arg(meta_function->name()).arg(meta_class->name());
1375 .arg(meta_function->name()).arg(meta_class->name());
1376 ReportHandler::warning(warn);
1376 ReportHandler::warning(warn);
1377 }
1377 }
1378
1378
1379 if (meta_function->isSignal() && !meta_class->isQObject()) {
1379 if (meta_function->isSignal() && !meta_class->isQObject()) {
1380 QString warn = QString("signal '%1' in non-QObject class '%2'")
1380 QString warn = QString("signal '%1' in non-QObject class '%2'")
1381 .arg(meta_function->name()).arg(meta_class->name());
1381 .arg(meta_function->name()).arg(meta_class->name());
1382 ReportHandler::warning(warn);
1382 ReportHandler::warning(warn);
1383 }
1383 }
1384
1384
1385 meta_class->addFunction(meta_function);
1385 meta_class->addFunction(meta_function);
1386 } else if (meta_function->isDestructor() && !meta_function->isPublic()) {
1386 } else if (meta_function->isDestructor() && !meta_function->isPublic()) {
1387 meta_class->setHasPublicDestructor(false);
1387 meta_class->setHasPublicDestructor(false);
1388 }
1388 }
1389 }
1389 }
1390 }
1390 }
1391 }
1391 }
1392
1392
1393 bool AbstractMetaBuilder::setupInheritance(AbstractMetaClass *meta_class)
1393 bool AbstractMetaBuilder::setupInheritance(AbstractMetaClass *meta_class)
1394 {
1394 {
1395 Q_ASSERT(!meta_class->isInterface());
1395 Q_ASSERT(!meta_class->isInterface());
1396
1396
1397 if (m_setup_inheritance_done.contains(meta_class))
1397 if (m_setup_inheritance_done.contains(meta_class))
1398 return true;
1398 return true;
1399 m_setup_inheritance_done.insert(meta_class);
1399 m_setup_inheritance_done.insert(meta_class);
1400
1400
1401 QStringList base_classes = meta_class->baseClassNames();
1401 QStringList base_classes = meta_class->baseClassNames();
1402
1402
1403 TypeDatabase *types = TypeDatabase::instance();
1403 TypeDatabase *types = TypeDatabase::instance();
1404
1404
1405 // we only support our own containers and ONLY if there is only one baseclass
1405 // we only support our own containers and ONLY if there is only one baseclass
1406 if (base_classes.size() == 1 && base_classes.first().count('<') == 1) {
1406 if (base_classes.size() == 1 && base_classes.first().count('<') == 1) {
1407 QStringList scope = meta_class->typeEntry()->qualifiedCppName().split("::");
1407 QStringList scope = meta_class->typeEntry()->qualifiedCppName().split("::");
1408 scope.removeLast();
1408 scope.removeLast();
1409 for (int i=scope.size(); i>=0; --i) {
1409 for (int i=scope.size(); i>=0; --i) {
1410 QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join("::") + "::" : QString();
1410 QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join("::") + "::" : QString();
1411 QString complete_name = prefix + base_classes.first();
1411 QString complete_name = prefix + base_classes.first();
1412 TypeParser::Info info = TypeParser::parse(complete_name);
1412 TypeParser::Info info = TypeParser::parse(complete_name);
1413 QString base_name = info.qualified_name.join("::");
1413 QString base_name = info.qualified_name.join("::");
1414
1414
1415 AbstractMetaClass *templ = 0;
1415 AbstractMetaClass *templ = 0;
1416 foreach (AbstractMetaClass *c, m_templates) {
1416 foreach (AbstractMetaClass *c, m_templates) {
1417 if (c->typeEntry()->name() == base_name) {
1417 if (c->typeEntry()->name() == base_name) {
1418 templ = c;
1418 templ = c;
1419 break;
1419 break;
1420 }
1420 }
1421 }
1421 }
1422
1422
1423 if (templ == 0)
1423 if (templ == 0)
1424 templ = m_meta_classes.findClass(base_name);
1424 templ = m_meta_classes.findClass(base_name);
1425
1425
1426 if (templ) {
1426 if (templ) {
1427 setupInheritance(templ);
1427 setupInheritance(templ);
1428 inheritTemplate(meta_class, templ, info);
1428 inheritTemplate(meta_class, templ, info);
1429 return true;
1429 return true;
1430 }
1430 }
1431 }
1431 }
1432
1432
1433 ReportHandler::warning(QString("template baseclass '%1' of '%2' is not known")
1433 ReportHandler::warning(QString("template baseclass '%1' of '%2' is not known")
1434 .arg(base_classes.first())
1434 .arg(base_classes.first())
1435 .arg(meta_class->name()));
1435 .arg(meta_class->name()));
1436 return false;
1436 return false;
1437 }
1437 }
1438
1438
1439 int primary = -1;
1439 int primary = -1;
1440 int primaries = 0;
1440 int primaries = 0;
1441 for (int i=0; i<base_classes.size(); ++i) {
1441 for (int i=0; i<base_classes.size(); ++i) {
1442
1442
1443 if (types->isClassRejected(base_classes.at(i)))
1443 if (types->isClassRejected(base_classes.at(i)))
1444 continue;
1444 continue;
1445
1445
1446 TypeEntry *base_class_entry = types->findType(base_classes.at(i));
1446 TypeEntry *base_class_entry = types->findType(base_classes.at(i));
1447 if (!base_class_entry) {
1447 if (!base_class_entry) {
1448 ReportHandler::warning(QString("class '%1' inherits from unknown base class '%2'")
1448 ReportHandler::warning(QString("class '%1' inherits from unknown base class '%2'")
1449 .arg(meta_class->name()).arg(base_classes.at(i)));
1449 .arg(meta_class->name()).arg(base_classes.at(i)));
1450 }
1450 }
1451
1451
1452 // true for primary base class
1452 // true for primary base class
1453 else if (!base_class_entry->designatedInterface()) {
1453 else if (!base_class_entry->designatedInterface()) {
1454 if (primaries > 0) {
1454 if (primaries > 0) {
1455 ReportHandler::warning(QString("class '%1' has multiple primary base classes"
1455 ReportHandler::warning(QString("class '%1' has multiple primary base classes"
1456 " '%2' and '%3'")
1456 " '%2' and '%3'")
1457 .arg(meta_class->name())
1457 .arg(meta_class->name())
1458 .arg(base_classes.at(primary))
1458 .arg(base_classes.at(primary))
1459 .arg(base_class_entry->name()));
1459 .arg(base_class_entry->name()));
1460 return false;
1460 return false;
1461 }
1461 }
1462 primaries++;
1462 primaries++;
1463 primary = i;
1463 primary = i;
1464 }
1464 }
1465 }
1465 }
1466
1466
1467 if (primary >= 0) {
1467 if (primary >= 0) {
1468 AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(primary));
1468 AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(primary));
1469 if (!base_class) {
1469 if (!base_class) {
1470 ReportHandler::warning(QString("unknown baseclass for '%1': '%2'")
1470 ReportHandler::warning(QString("unknown baseclass for '%1': '%2'")
1471 .arg(meta_class->name())
1471 .arg(meta_class->name())
1472 .arg(base_classes.at(primary)));
1472 .arg(base_classes.at(primary)));
1473 return false;
1473 return false;
1474 }
1474 }
1475 meta_class->setBaseClass(base_class);
1475 meta_class->setBaseClass(base_class);
1476
1476
1477 if (meta_class->typeEntry()->designatedInterface() != 0 && meta_class->isQObject()) {
1477 if (meta_class->typeEntry()->designatedInterface() != 0 && meta_class->isQObject()) {
1478 ReportHandler::warning(QString("QObject extended by interface type '%1'. This is not supported and the generated Java code will not compile.")
1478 ReportHandler::warning(QString("QObject extended by interface type '%1'. This is not supported and the generated Java code will not compile.")
1479 .arg(meta_class->name()));
1479 .arg(meta_class->name()));
1480 } else if (meta_class->typeEntry()->designatedInterface() != 0 && base_class != 0 && !base_class->isInterface()) {
1480 } else if (meta_class->typeEntry()->designatedInterface() != 0 && base_class != 0 && !base_class->isInterface()) {
1481 ReportHandler::warning(QString("object type '%1' extended by interface type '%2'. The resulting API will be less expressive than the original.")
1481 ReportHandler::warning(QString("object type '%1' extended by interface type '%2'. The resulting API will be less expressive than the original.")
1482 .arg(base_class->name())
1482 .arg(base_class->name())
1483 .arg(meta_class->name()));
1483 .arg(meta_class->name()));
1484 }
1484 }
1485
1485
1486 }
1486 }
1487
1487
1488 for (int i=0; i<base_classes.size(); ++i) {
1488 for (int i=0; i<base_classes.size(); ++i) {
1489 if (types->isClassRejected(base_classes.at(i)))
1489 if (types->isClassRejected(base_classes.at(i)))
1490 continue;
1490 continue;
1491
1491
1492 if (i != primary) {
1492 if (i != primary) {
1493 AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(i));
1493 AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(i));
1494 if (base_class == 0) {
1494 if (base_class == 0) {
1495 ReportHandler::warning(QString("class not found for setup inheritance '%1'").arg(base_classes.at(i)));
1495 ReportHandler::warning(QString("class not found for setup inheritance '%1'").arg(base_classes.at(i)));
1496 return false;
1496 return false;
1497 }
1497 }
1498
1498
1499 setupInheritance(base_class);
1499 setupInheritance(base_class);
1500
1500
1501 QString interface_name = InterfaceTypeEntry::interfaceName(base_class->name());
1501 QString interface_name = InterfaceTypeEntry::interfaceName(base_class->name());
1502 AbstractMetaClass *iface = m_meta_classes.findClass(interface_name);
1502 AbstractMetaClass *iface = m_meta_classes.findClass(interface_name);
1503 if (!iface) {
1503 if (!iface) {
1504 ReportHandler::warning(QString("unknown interface for '%1': '%2'")
1504 ReportHandler::warning(QString("unknown interface for '%1': '%2'")
1505 .arg(meta_class->name())
1505 .arg(meta_class->name())
1506 .arg(interface_name));
1506 .arg(interface_name));
1507 return false;
1507 return false;
1508 }
1508 }
1509 meta_class->addInterface(iface);
1509 meta_class->addInterface(iface);
1510
1510
1511 AbstractMetaClassList interfaces = iface->interfaces();
1511 AbstractMetaClassList interfaces = iface->interfaces();
1512 foreach (AbstractMetaClass *iface, interfaces)
1512 foreach (AbstractMetaClass *iface, interfaces)
1513 meta_class->addInterface(iface);
1513 meta_class->addInterface(iface);
1514 }
1514 }
1515 }
1515 }
1516
1516
1517 return true;
1517 return true;
1518 }
1518 }
1519
1519
1520 void AbstractMetaBuilder::traverseEnums(ScopeModelItem scope_item, AbstractMetaClass *meta_class, const QStringList &enumsDeclarations)
1520 void AbstractMetaBuilder::traverseEnums(ScopeModelItem scope_item, AbstractMetaClass *meta_class, const QStringList &enumsDeclarations)
1521 {
1521 {
1522 EnumList enums = scope_item->enums();
1522 EnumList enums = scope_item->enums();
1523 foreach (EnumModelItem enum_item, enums) {
1523 foreach (EnumModelItem enum_item, enums) {
1524 AbstractMetaEnum *meta_enum = traverseEnum(enum_item, meta_class, QSet<QString>::fromList(enumsDeclarations));
1524 AbstractMetaEnum *meta_enum = traverseEnum(enum_item, meta_class, QSet<QString>::fromList(enumsDeclarations));
1525 if (meta_enum) {
1525 if (meta_enum) {
1526 meta_enum->setOriginalAttributes(meta_enum->attributes());
1526 meta_enum->setOriginalAttributes(meta_enum->attributes());
1527 meta_class->addEnum(meta_enum);
1527 meta_class->addEnum(meta_enum);
1528 meta_enum->setEnclosingClass(meta_class);
1528 meta_enum->setEnclosingClass(meta_class);
1529 }
1529 }
1530 }
1530 }
1531 }
1531 }
1532
1532
1533 AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(FunctionModelItem function_item)
1533 AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(FunctionModelItem function_item)
1534 {
1534 {
1535 QString function_name = function_item->name();
1535 QString function_name = function_item->name();
1536 QString class_name = m_current_class->typeEntry()->qualifiedCppName();
1536 QString class_name = m_current_class->typeEntry()->qualifiedCppName();
1537
1537
1538 if (TypeDatabase::instance()->isFunctionRejected(class_name, function_name)) {
1538 if (TypeDatabase::instance()->isFunctionRejected(class_name, function_name)) {
1539 m_rejected_functions.insert(class_name + "::" + function_name, GenerationDisabled);
1539 m_rejected_functions.insert(class_name + "::" + function_name, GenerationDisabled);
1540 return 0;
1540 return 0;
1541 }
1541 }
1542
1542
1543
1543
1544 Q_ASSERT(function_item->functionType() == CodeModel::Normal
1544 Q_ASSERT(function_item->functionType() == CodeModel::Normal
1545 || function_item->functionType() == CodeModel::Signal
1545 || function_item->functionType() == CodeModel::Signal
1546 || function_item->functionType() == CodeModel::Slot);
1546 || function_item->functionType() == CodeModel::Slot);
1547
1547
1548 if (function_item->isFriend())
1548 if (function_item->isFriend())
1549 return 0;
1549 return 0;
1550
1550
1551
1551
1552 QString cast_type;
1552 QString cast_type;
1553
1553
1554 if (function_name.startsWith("operator")) {
1554 if (function_name.startsWith("operator")) {
1555 function_name = rename_operator(function_name.mid(8));
1555 function_name = rename_operator(function_name.mid(8));
1556 if (function_name.isEmpty()) {
1556 if (function_name.isEmpty()) {
1557 m_rejected_functions.insert(class_name + "::" + function_name,
1557 m_rejected_functions.insert(class_name + "::" + function_name,
1558 GenerationDisabled);
1558 GenerationDisabled);
1559 return 0;
1559 return 0;
1560 }
1560 }
1561 if (function_name.contains("_cast_"))
1561 if (function_name.contains("_cast_"))
1562 cast_type = function_name.mid(14).trimmed();
1562 cast_type = function_name.mid(14).trimmed();
1563 }
1563 }
1564
1564
1565 AbstractMetaFunction *meta_function = createMetaFunction();
1565 AbstractMetaFunction *meta_function = createMetaFunction();
1566 meta_function->setConstant(function_item->isConstant());
1566 meta_function->setConstant(function_item->isConstant());
1567
1567
1568 ReportHandler::debugMedium(QString(" - %2()").arg(function_name));
1568 ReportHandler::debugMedium(QString(" - %2()").arg(function_name));
1569
1569
1570 meta_function->setName(function_name);
1570 meta_function->setName(function_name);
1571 meta_function->setOriginalName(function_item->name());
1571 meta_function->setOriginalName(function_item->name());
1572
1572
1573 if (function_item->isAbstract())
1573 if (function_item->isAbstract())
1574 *meta_function += AbstractMetaAttributes::Abstract;
1574 *meta_function += AbstractMetaAttributes::Abstract;
1575
1575
1576 if (!meta_function->isAbstract())
1576 if (!meta_function->isAbstract())
1577 *meta_function += AbstractMetaAttributes::Native;
1577 *meta_function += AbstractMetaAttributes::Native;
1578
1578
1579 if (!function_item->isVirtual())
1579 if (!function_item->isVirtual())
1580 *meta_function += AbstractMetaAttributes::Final;
1580 *meta_function += AbstractMetaAttributes::Final;
1581
1581
1582 if (function_item->isInvokable())
1582 if (function_item->isInvokable())
1583 *meta_function += AbstractMetaAttributes::Invokable;
1583 *meta_function += AbstractMetaAttributes::Invokable;
1584
1584
1585 if (function_item->isStatic()) {
1585 if (function_item->isStatic()) {
1586 *meta_function += AbstractMetaAttributes::Static;
1586 *meta_function += AbstractMetaAttributes::Static;
1587 *meta_function += AbstractMetaAttributes::Final;
1587 *meta_function += AbstractMetaAttributes::Final;
1588 }
1588 }
1589
1589
1590 // Access rights
1590 // Access rights
1591 if (function_item->accessPolicy() == CodeModel::Public)
1591 if (function_item->accessPolicy() == CodeModel::Public)
1592 *meta_function += AbstractMetaAttributes::Public;
1592 *meta_function += AbstractMetaAttributes::Public;
1593 else if (function_item->accessPolicy() == CodeModel::Private)
1593 else if (function_item->accessPolicy() == CodeModel::Private)
1594 *meta_function += AbstractMetaAttributes::Private;
1594 *meta_function += AbstractMetaAttributes::Private;
1595 else
1595 else
1596 *meta_function += AbstractMetaAttributes::Protected;
1596 *meta_function += AbstractMetaAttributes::Protected;
1597
1597
1598
1598
1599 QString stripped_class_name = class_name;
1599 QString stripped_class_name = class_name;
1600 int cc_pos = stripped_class_name.lastIndexOf("::");
1600 int cc_pos = stripped_class_name.lastIndexOf("::");
1601 if (cc_pos > 0)
1601 if (cc_pos > 0)
1602 stripped_class_name = stripped_class_name.mid(cc_pos + 2);
1602 stripped_class_name = stripped_class_name.mid(cc_pos + 2);
1603
1603
1604 TypeInfo function_type = function_item->type();
1604 TypeInfo function_type = function_item->type();
1605 if (function_name.startsWith('~')) {
1605 if (function_name.startsWith('~')) {
1606 meta_function->setFunctionType(AbstractMetaFunction::DestructorFunction);
1606 meta_function->setFunctionType(AbstractMetaFunction::DestructorFunction);
1607 meta_function->setInvalid(true);
1607 meta_function->setInvalid(true);
1608 } else if (strip_template_args(function_name) == stripped_class_name) {
1608 } else if (strip_template_args(function_name) == stripped_class_name) {
1609 meta_function->setFunctionType(AbstractMetaFunction::ConstructorFunction);
1609 meta_function->setFunctionType(AbstractMetaFunction::ConstructorFunction);
1610 meta_function->setName(m_current_class->name());
1610 meta_function->setName(m_current_class->name());
1611 } else {
1611 } else {
1612 bool ok;
1612 bool ok;
1613 AbstractMetaType *type = 0;
1613 AbstractMetaType *type = 0;
1614
1614
1615 if (!cast_type.isEmpty()) {
1615 if (!cast_type.isEmpty()) {
1616 TypeInfo info;
1616 TypeInfo info;
1617 info.setQualifiedName(QStringList(cast_type));
1617 info.setQualifiedName(QStringList(cast_type));
1618 type = translateType(info, &ok);
1618 type = translateType(info, &ok);
1619 } else {
1619 } else {
1620 type = translateType(function_type, &ok);
1620 type = translateType(function_type, &ok);
1621 }
1621 }
1622
1622
1623 if (!ok) {
1623 if (!ok) {
1624 ReportHandler::warning(QString("skipping function '%1::%2', unmatched return type '%3'")
1624 ReportHandler::warning(QString("skipping function '%1::%2', unmatched return type '%3'")
1625 .arg(class_name)
1625 .arg(class_name)
1626 .arg(function_item->name())
1626 .arg(function_item->name())
1627 .arg(function_item->type().toString()));
1627 .arg(function_item->type().toString()));
1628 m_rejected_functions[class_name + "::" + function_name] =
1628 m_rejected_functions[class_name + "::" + function_name] =
1629 UnmatchedReturnType;
1629 UnmatchedReturnType;
1630 meta_function->setInvalid(true);
1630 meta_function->setInvalid(true);
1631 return meta_function;
1631 return meta_function;
1632 }
1632 }
1633 meta_function->setType(type);
1633 meta_function->setType(type);
1634
1634
1635 if (function_item->functionType() == CodeModel::Signal)
1635 if (function_item->functionType() == CodeModel::Signal)
1636 meta_function->setFunctionType(AbstractMetaFunction::SignalFunction);
1636 meta_function->setFunctionType(AbstractMetaFunction::SignalFunction);
1637 else if (function_item->functionType() == CodeModel::Slot)
1637 else if (function_item->functionType() == CodeModel::Slot)
1638 meta_function->setFunctionType(AbstractMetaFunction::SlotFunction);
1638 meta_function->setFunctionType(AbstractMetaFunction::SlotFunction);
1639 }
1639 }
1640
1640
1641 ArgumentList arguments = function_item->arguments();
1641 ArgumentList arguments = function_item->arguments();
1642 AbstractMetaArgumentList meta_arguments;
1642 AbstractMetaArgumentList meta_arguments;
1643
1643
1644 int first_default_argument = 0;
1644 int first_default_argument = 0;
1645 for (int i=0; i<arguments.size(); ++i) {
1645 for (int i=0; i<arguments.size(); ++i) {
1646 ArgumentModelItem arg = arguments.at(i);
1646 ArgumentModelItem arg = arguments.at(i);
1647
1647
1648 bool ok;
1648 bool ok;
1649 AbstractMetaType *meta_type = translateType(arg->type(), &ok);
1649 AbstractMetaType *meta_type = translateType(arg->type(), &ok);
1650 if (!meta_type || !ok) {
1650 if (!meta_type || !ok) {
1651 ReportHandler::warning(QString("skipping function '%1::%2', "
1651 ReportHandler::warning(QString("skipping function '%1::%2', "
1652 "unmatched parameter type '%3'")
1652 "unmatched parameter type '%3'")
1653 .arg(class_name)
1653 .arg(class_name)
1654 .arg(function_item->name())
1654 .arg(function_item->name())
1655 .arg(arg->type().toString()));
1655 .arg(arg->type().toString()));
1656 m_rejected_functions[class_name + "::" + function_name] =
1656 m_rejected_functions[class_name + "::" + function_name] =
1657 UnmatchedArgumentType;
1657 UnmatchedArgumentType;
1658 meta_function->setInvalid(true);
1658 meta_function->setInvalid(true);
1659 return meta_function;
1659 return meta_function;
1660 }
1660 }
1661 AbstractMetaArgument *meta_argument = createMetaArgument();
1661 AbstractMetaArgument *meta_argument = createMetaArgument();
1662 meta_argument->setType(meta_type);
1662 meta_argument->setType(meta_type);
1663 meta_argument->setName(arg->name());
1663 meta_argument->setName(arg->name());
1664 meta_argument->setArgumentIndex(i);
1664 meta_argument->setArgumentIndex(i);
1665 meta_arguments << meta_argument;
1665 meta_arguments << meta_argument;
1666 }
1666 }
1667
1667
1668 meta_function->setArguments(meta_arguments);
1668 meta_function->setArguments(meta_arguments);
1669
1669
1670 // Find the correct default values
1670 // Find the correct default values
1671 for (int i=0; i<arguments.size(); ++i) {
1671 for (int i=0; i<arguments.size(); ++i) {
1672 ArgumentModelItem arg = arguments.at(i);
1672 ArgumentModelItem arg = arguments.at(i);
1673 AbstractMetaArgument *meta_arg = meta_arguments.at(i);
1673 AbstractMetaArgument *meta_arg = meta_arguments.at(i);
1674 if (arg->defaultValue()) {
1674 if (arg->defaultValue()) {
1675 QString expr = arg->defaultValueExpression();
1675 QString expr = arg->defaultValueExpression();
1676 if (!expr.isEmpty())
1676 if (!expr.isEmpty())
1677 meta_arg->setOriginalDefaultValueExpression(expr);
1677 meta_arg->setOriginalDefaultValueExpression(expr);
1678
1678
1679 expr = translateDefaultValue(arg, meta_arg->type(), meta_function, m_current_class, i);
1679 expr = translateDefaultValue(arg, meta_arg->type(), meta_function, m_current_class, i);
1680 if (expr.isEmpty()) {
1680 if (expr.isEmpty()) {
1681 first_default_argument = i;
1681 first_default_argument = i;
1682 } else {
1682 } else {
1683 meta_arg->setDefaultValueExpression(expr);
1683 meta_arg->setDefaultValueExpression(expr);
1684 }
1684 }
1685
1685
1686 if (meta_arg->type()->isEnum() || meta_arg->type()->isFlags()) {
1686 if (meta_arg->type()->isEnum() || meta_arg->type()->isFlags()) {
1687 m_enum_default_arguments
1687 m_enum_default_arguments
1688 << QPair<AbstractMetaArgument *, AbstractMetaFunction *>(meta_arg, meta_function);
1688 << QPair<AbstractMetaArgument *, AbstractMetaFunction *>(meta_arg, meta_function);
1689 }
1689 }
1690
1690
1691 }
1691 }
1692 }
1692 }
1693
1693
1694 // If we where not able to translate the default argument make it
1694 // If we where not able to translate the default argument make it
1695 // reset all default arguments before this one too.
1695 // reset all default arguments before this one too.
1696 for (int i=0; i<first_default_argument; ++i)
1696 for (int i=0; i<first_default_argument; ++i)
1697 meta_arguments[i]->setDefaultValueExpression(QString());
1697 meta_arguments[i]->setDefaultValueExpression(QString());
1698
1698
1699 if (ReportHandler::debugLevel() == ReportHandler::FullDebug)
1699 if (ReportHandler::debugLevel() == ReportHandler::FullDebug)
1700 foreach(AbstractMetaArgument *arg, meta_arguments)
1700 foreach(AbstractMetaArgument *arg, meta_arguments)
1701 ReportHandler::debugFull(" - " + arg->toString());
1701 ReportHandler::debugFull(" - " + arg->toString());
1702
1702
1703 return meta_function;
1703 return meta_function;
1704 }
1704 }
1705
1705
1706
1706
1707 AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, bool *ok, bool resolveType, bool resolveScope)
1707 AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, bool *ok, bool resolveType, bool resolveScope)
1708 {
1708 {
1709 Q_ASSERT(ok);
1709 Q_ASSERT(ok);
1710 *ok = true;
1710 *ok = true;
1711
1711
1712 // 1. Test the type info without resolving typedefs in case this is present in the
1712 // 1. Test the type info without resolving typedefs in case this is present in the
1713 // type system
1713 // type system
1714 TypeInfo typei;
1714 TypeInfo typei;
1715 if (resolveType) {
1715 if (resolveType) {
1716 bool isok;
1716 bool isok;
1717 AbstractMetaType *t = translateType(_typei, &isok, false, resolveScope);
1717 AbstractMetaType *t = translateType(_typei, &isok, false, resolveScope);
1718 if (t != 0 && isok)
1718 if (t != 0 && isok)
1719 return t;
1719 return t;
1720 }
1720 }
1721
1721
1722 if (!resolveType)
1722 if (!resolveType)
1723 typei = _typei;
1723 typei = _typei;
1724 else {
1724 else {
1725 // Go through all parts of the current scope (including global namespace)
1725 // Go through all parts of the current scope (including global namespace)
1726 // to resolve typedefs. The parser does not properly resolve typedefs in
1726 // to resolve typedefs. The parser does not properly resolve typedefs in
1727 // the global scope when they are referenced from inside a namespace.
1727 // the global scope when they are referenced from inside a namespace.
1728 // This is a work around to fix this bug since fixing it in resolveType
1728 // This is a work around to fix this bug since fixing it in resolveType
1729 // seemed non-trivial
1729 // seemed non-trivial
1730 int i = m_scopes.size() - 1;
1730 int i = m_scopes.size() - 1;
1731 while (i >= 0) {
1731 while (i >= 0) {
1732 typei = TypeInfo::resolveType(_typei, m_scopes.at(i--)->toItem());
1732 typei = TypeInfo::resolveType(_typei, m_scopes.at(i--)->toItem());
1733 if (typei.qualifiedName().join("::") != _typei.qualifiedName().join("::"))
1733 if (typei.qualifiedName().join("::") != _typei.qualifiedName().join("::"))
1734 break;
1734 break;
1735 }
1735 }
1736
1736
1737 }
1737 }
1738
1738
1739 if (typei.isFunctionPointer()) {
1739 if (typei.isFunctionPointer()) {
1740 *ok = false;
1740 *ok = false;
1741 return 0;
1741 return 0;
1742 }
1742 }
1743
1743
1744 TypeParser::Info typeInfo = TypeParser::parse(typei.toString());
1744 TypeParser::Info typeInfo = TypeParser::parse(typei.toString());
1745 if (typeInfo.is_busted) {
1745 if (typeInfo.is_busted) {
1746 *ok = false;
1746 *ok = false;
1747 return 0;
1747 return 0;
1748 }
1748 }
1749
1749
1750 // 2. Handle pointers specified as arrays with unspecified size
1750 // 2. Handle pointers specified as arrays with unspecified size
1751 bool array_of_unspecified_size = false;
1751 bool array_of_unspecified_size = false;
1752 if (typeInfo.arrays.size() > 0) {
1752 if (typeInfo.arrays.size() > 0) {
1753 array_of_unspecified_size = true;
1753 array_of_unspecified_size = true;
1754 for (int i=0; i<typeInfo.arrays.size(); ++i)
1754 for (int i=0; i<typeInfo.arrays.size(); ++i)
1755 array_of_unspecified_size = array_of_unspecified_size && typeInfo.arrays.at(i).isEmpty();
1755 array_of_unspecified_size = array_of_unspecified_size && typeInfo.arrays.at(i).isEmpty();
1756
1756
1757 if (!array_of_unspecified_size) {
1757 if (!array_of_unspecified_size) {
1758 TypeInfo newInfo;
1758 TypeInfo newInfo;
1759 //newInfo.setArguments(typei.arguments());
1759 //newInfo.setArguments(typei.arguments());
1760 newInfo.setIndirections(typei.indirections());
1760 newInfo.setIndirections(typei.indirections());
1761 newInfo.setConstant(typei.isConstant());
1761 newInfo.setConstant(typei.isConstant());
1762 newInfo.setFunctionPointer(typei.isFunctionPointer());
1762 newInfo.setFunctionPointer(typei.isFunctionPointer());
1763 newInfo.setQualifiedName(typei.qualifiedName());
1763 newInfo.setQualifiedName(typei.qualifiedName());
1764 newInfo.setReference(typei.isReference());
1764 newInfo.setReference(typei.isReference());
1765 newInfo.setVolatile(typei.isVolatile());
1765 newInfo.setVolatile(typei.isVolatile());
1766
1766
1767 AbstractMetaType *elementType = translateType(newInfo, ok);
1767 AbstractMetaType *elementType = translateType(newInfo, ok);
1768 if (!(*ok))
1768 if (!(*ok))
1769 return 0;
1769 return 0;
1770
1770
1771 for (int i=typeInfo.arrays.size()-1; i>=0; --i) {
1771 for (int i=typeInfo.arrays.size()-1; i>=0; --i) {
1772 QString s = typeInfo.arrays.at(i);
1772 QString s = typeInfo.arrays.at(i);
1773 bool isok;
1773 bool isok;
1774
1774
1775 int elems = s.toInt(&isok);
1775 int elems = s.toInt(&isok);
1776 if (!isok)
1776 if (!isok)
1777 return 0;
1777 return 0;
1778
1778
1779 AbstractMetaType *arrayType = createMetaType();
1779 AbstractMetaType *arrayType = createMetaType();
1780 arrayType->setArrayElementCount(elems);
1780 arrayType->setArrayElementCount(elems);
1781 arrayType->setArrayElementType(elementType);
1781 arrayType->setArrayElementType(elementType);
1782 arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry()));
1782 arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry()));
1783 decideUsagePattern(arrayType);
1783 decideUsagePattern(arrayType);
1784
1784
1785 elementType = arrayType;
1785 elementType = arrayType;
1786 }
1786 }
1787
1787
1788 return elementType;
1788 return elementType;
1789 } else {
1789 } else {
1790 typeInfo.indirections += typeInfo.arrays.size();
1790 typeInfo.indirections += typeInfo.arrays.size();
1791 }
1791 }
1792 }
1792 }
1793
1793
1794 QStringList qualifier_list = typeInfo.qualified_name;
1794 QStringList qualifier_list = typeInfo.qualified_name;
1795 if (qualifier_list.isEmpty()) {
1795 if (qualifier_list.isEmpty()) {
1796 ReportHandler::warning(QString("horribly broken type '%1'").arg(_typei.toString()));
1796 ReportHandler::warning(QString("horribly broken type '%1'").arg(_typei.toString()));
1797 *ok = false;
1797 *ok = false;
1798 return 0;
1798 return 0;
1799 }
1799 }
1800
1800
1801 QString qualified_name = qualifier_list.join("::");
1801 QString qualified_name = qualifier_list.join("::");
1802 QString name = qualifier_list.takeLast();
1802 QString name = qualifier_list.takeLast();
1803
1803
1804 // 3. Special case 'void' type
1804 // 3. Special case 'void' type
1805 if (name == "void" && typeInfo.indirections == 0) {
1805 if (name == "void" && typeInfo.indirections == 0) {
1806 return 0;
1806 return 0;
1807 }
1807 }
1808
1808
1809 // 4. Special case QFlags (include instantiation in name)
1809 // 4. Special case QFlags (include instantiation in name)
1810 if (qualified_name == "QFlags")
1810 if (qualified_name == "QFlags")
1811 qualified_name = typeInfo.toString();
1811 qualified_name = typeInfo.toString();
1812
1812
1813 // 5. Try to find the type
1813 // 5. Try to find the type
1814 const TypeEntry *type = TypeDatabase::instance()->findType(qualified_name);
1814 const TypeEntry *type = TypeDatabase::instance()->findType(qualified_name);
1815
1815
1816 // 6. No? Try looking it up as a flags type
1816 // 6. No? Try looking it up as a flags type
1817 if (!type)
1817 if (!type)
1818 type = TypeDatabase::instance()->findFlagsType(qualified_name);
1818 type = TypeDatabase::instance()->findFlagsType(qualified_name);
1819
1819
1820 // 7. No? Try looking it up as a container type
1820 // 7. No? Try looking it up as a container type
1821 if (!type)
1821 if (!type)
1822 type = TypeDatabase::instance()->findContainerType(name);
1822 type = TypeDatabase::instance()->findContainerType(name);
1823
1823
1824 // 8. No? Check if the current class is a template and this type is one
1824 // 8. No? Check if the current class is a template and this type is one
1825 // of the parameters.
1825 // of the parameters.
1826 if (type == 0 && m_current_class != 0) {
1826 if (type == 0 && m_current_class != 0) {
1827 QList<TypeEntry *> template_args = m_current_class->templateArguments();
1827 QList<TypeEntry *> template_args = m_current_class->templateArguments();
1828 foreach (TypeEntry *te, template_args) {
1828 foreach (TypeEntry *te, template_args) {
1829 if (te->name() == qualified_name)
1829 if (te->name() == qualified_name)
1830 type = te;
1830 type = te;
1831 }
1831 }
1832 }
1832 }
1833
1833
1834 // 9. Try finding the type by prefixing it with the current
1834 // 9. Try finding the type by prefixing it with the current
1835 // context and all baseclasses of the current context
1835 // context and all baseclasses of the current context
1836 if (!type && !TypeDatabase::instance()->isClassRejected(qualified_name) && m_current_class != 0 && resolveScope) {
1836 if (!type && !TypeDatabase::instance()->isClassRejected(qualified_name) && m_current_class != 0 && resolveScope) {
1837 QStringList contexts;
1837 QStringList contexts;
1838 contexts.append(m_current_class->qualifiedCppName());
1838 contexts.append(m_current_class->qualifiedCppName());
1839 contexts.append(currentScope()->qualifiedName().join("::"));
1839 contexts.append(currentScope()->qualifiedName().join("::"));
1840
1840
1841
1841
1842 TypeInfo info = typei;
1842 TypeInfo info = typei;
1843 bool subclasses_done = false;
1843 bool subclasses_done = false;
1844 while (!contexts.isEmpty() && type == 0) {
1844 while (!contexts.isEmpty() && type == 0) {
1845 //type = TypeDatabase::instance()->findType(contexts.at(0) + "::" + qualified_name);
1845 //type = TypeDatabase::instance()->findType(contexts.at(0) + "::" + qualified_name);
1846
1846
1847 bool isok;
1847 bool isok;
1848 info.setQualifiedName(QStringList() << contexts.at(0) << qualified_name);
1848 info.setQualifiedName(QStringList() << contexts.at(0) << qualified_name);
1849 AbstractMetaType *t = translateType(info, &isok, true, false);
1849 AbstractMetaType *t = translateType(info, &isok, true, false);
1850 if (t != 0 && isok)
1850 if (t != 0 && isok)
1851 return t;
1851 return t;
1852
1852
1853 ClassModelItem item = m_dom->findClass(contexts.at(0));
1853 ClassModelItem item = m_dom->findClass(contexts.at(0));
1854 if (item != 0)
1854 if (item != 0)
1855 contexts += item->baseClasses();
1855 contexts += item->baseClasses();
1856 contexts.pop_front();
1856 contexts.pop_front();
1857
1857
1858 // 10. Last resort: Special cased prefix of Qt namespace since the meta object implicitly inherits this, so
1858 // 10. Last resort: Special cased prefix of Qt namespace since the meta object implicitly inherits this, so
1859 // enum types from there may be addressed without any scope resolution in properties.
1859 // enum types from there may be addressed without any scope resolution in properties.
1860 if (contexts.size() == 0 && !subclasses_done) {
1860 if (contexts.size() == 0 && !subclasses_done) {
1861 contexts << "Qt";
1861 contexts << "Qt";
1862 subclasses_done = true;
1862 subclasses_done = true;
1863 }
1863 }
1864 }
1864 }
1865
1865
1866 }
1866 }
1867
1867
1868 if (!type) {
1868 if (!type) {
1869 *ok = false;
1869 *ok = false;
1870 return 0;
1870 return 0;
1871 }
1871 }
1872
1872
1873 // Used to for diagnostics later...
1873 // Used to for diagnostics later...
1874 m_used_types << type;
1874 m_used_types << type;
1875
1875
1876 // These are only implicit and should not appear in code...
1876 // These are only implicit and should not appear in code...
1877 Q_ASSERT(!type->isInterface());
1877 Q_ASSERT(!type->isInterface());
1878
1878
1879 AbstractMetaType *meta_type = createMetaType();
1879 AbstractMetaType *meta_type = createMetaType();
1880 meta_type->setTypeEntry(type);
1880 meta_type->setTypeEntry(type);
1881 meta_type->setIndirections(typeInfo.indirections);
1881 meta_type->setIndirections(typeInfo.indirections);
1882 meta_type->setReference(typeInfo.is_reference);
1882 meta_type->setReference(typeInfo.is_reference);
1883 meta_type->setConstant(typeInfo.is_constant);
1883 meta_type->setConstant(typeInfo.is_constant);
1884 meta_type->setOriginalTypeDescription(_typei.toString());
1884 meta_type->setOriginalTypeDescription(_typei.toString());
1885 decideUsagePattern(meta_type);
1885 decideUsagePattern(meta_type);
1886
1886
1887 if (meta_type->typeEntry()->isContainer()) {
1887 if (meta_type->typeEntry()->isContainer()) {
1888 ContainerTypeEntry::Type container_type = static_cast<const ContainerTypeEntry *>(type)->type();
1888 ContainerTypeEntry::Type container_type = static_cast<const ContainerTypeEntry *>(type)->type();
1889
1889
1890 if (container_type == ContainerTypeEntry::StringListContainer) {
1890 if (container_type == ContainerTypeEntry::StringListContainer) {
1891 TypeInfo info;
1891 TypeInfo info;
1892 info.setQualifiedName(QStringList() << "QString");
1892 info.setQualifiedName(QStringList() << "QString");
1893 AbstractMetaType *targ_type = translateType(info, ok);
1893 AbstractMetaType *targ_type = translateType(info, ok);
1894
1894
1895 Q_ASSERT(*ok);
1895 Q_ASSERT(*ok);
1896 Q_ASSERT(targ_type);
1896 Q_ASSERT(targ_type);
1897
1897
1898 meta_type->addInstantiation(targ_type);
1898 meta_type->addInstantiation(targ_type);
1899 meta_type->setInstantiationInCpp(false);
1899 meta_type->setInstantiationInCpp(false);
1900
1900
1901 } else {
1901 } else {
1902 foreach (const TypeParser::Info &ta, typeInfo.template_instantiations) {
1902 foreach (const TypeParser::Info &ta, typeInfo.template_instantiations) {
1903 TypeInfo info;
1903 TypeInfo info;
1904 info.setConstant(ta.is_constant);
1904 info.setConstant(ta.is_constant);
1905 info.setReference(ta.is_reference);
1905 info.setReference(ta.is_reference);
1906 info.setIndirections(ta.indirections);
1906 info.setIndirections(ta.indirections);
1907
1907
1908 info.setFunctionPointer(false);
1908 info.setFunctionPointer(false);
1909 info.setQualifiedName(ta.instantiationName().split("::"));
1909 info.setQualifiedName(ta.instantiationName().split("::"));
1910
1910
1911 AbstractMetaType *targ_type = translateType(info, ok);
1911 AbstractMetaType *targ_type = translateType(info, ok);
1912 if (!(*ok)) {
1912 if (!(*ok)) {
1913 delete meta_type;
1913 delete meta_type;
1914 return 0;
1914 return 0;
1915 }
1915 }
1916
1916
1917 meta_type->addInstantiation(targ_type);
1917 meta_type->addInstantiation(targ_type);
1918 }
1918 }
1919 }
1919 }
1920
1920
1921 if (container_type == ContainerTypeEntry::ListContainer
1921 if (container_type == ContainerTypeEntry::ListContainer
1922 || container_type == ContainerTypeEntry::VectorContainer
1922 || container_type == ContainerTypeEntry::VectorContainer
1923 || container_type == ContainerTypeEntry::StringListContainer) {
1923 || container_type == ContainerTypeEntry::StringListContainer) {
1924 Q_ASSERT(meta_type->instantiations().size() == 1);
1924 Q_ASSERT(meta_type->instantiations().size() == 1);
1925 }
1925 }
1926 }
1926 }
1927
1927
1928 return meta_type;
1928 return meta_type;
1929 }
1929 }
1930
1930
1931 void AbstractMetaBuilder::decideUsagePattern(AbstractMetaType *meta_type)
1931 void AbstractMetaBuilder::decideUsagePattern(AbstractMetaType *meta_type)
1932 {
1932 {
1933 const TypeEntry *type = meta_type->typeEntry();
1933 const TypeEntry *type = meta_type->typeEntry();
1934
1934
1935 if (type->isPrimitive() && (meta_type->actualIndirections() == 0
1935 if (type->isPrimitive() && (meta_type->actualIndirections() == 0
1936 || (meta_type->isConstant() && meta_type->isReference() && meta_type->indirections() == 0))) {
1936 || (meta_type->isConstant() && meta_type->isReference() && meta_type->indirections() == 0))) {
1937 meta_type->setTypeUsagePattern(AbstractMetaType::PrimitivePattern);
1937 meta_type->setTypeUsagePattern(AbstractMetaType::PrimitivePattern);
1938
1938
1939 } else if (type->isVoid()) {
1939 } else if (type->isVoid()) {
1940 meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
1940 meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
1941
1941
1942 } else if (type->isString()
1942 } else if (type->isString()
1943 && meta_type->indirections() == 0
1943 && meta_type->indirections() == 0
1944 && (meta_type->isConstant() == meta_type->isReference()
1944 && (meta_type->isConstant() == meta_type->isReference()
1945 || meta_type->isConstant())) {
1945 || meta_type->isConstant())) {
1946 meta_type->setTypeUsagePattern(AbstractMetaType::StringPattern);
1946 meta_type->setTypeUsagePattern(AbstractMetaType::StringPattern);
1947
1947
1948 } else if (type->isChar()
1948 } else if (type->isChar()
1949 && meta_type->indirections() == 0
1949 && meta_type->indirections() == 0
1950 && meta_type->isConstant() == meta_type->isReference()) {
1950 && meta_type->isConstant() == meta_type->isReference()) {
1951 meta_type->setTypeUsagePattern(AbstractMetaType::CharPattern);
1951 meta_type->setTypeUsagePattern(AbstractMetaType::CharPattern);
1952
1952
1953 } else if (type->isJObjectWrapper()
1953 } else if (type->isJObjectWrapper()
1954 && meta_type->indirections() == 0
1954 && meta_type->indirections() == 0
1955 && meta_type->isConstant() == meta_type->isReference()) {
1955 && meta_type->isConstant() == meta_type->isReference()) {
1956 meta_type->setTypeUsagePattern(AbstractMetaType::JObjectWrapperPattern);
1956 meta_type->setTypeUsagePattern(AbstractMetaType::JObjectWrapperPattern);
1957
1957
1958 } else if (type->isVariant()
1958 } else if (type->isVariant()
1959 && meta_type->indirections() == 0
1959 && meta_type->indirections() == 0
1960 && meta_type->isConstant() == meta_type->isReference()) {
1960 && meta_type->isConstant() == meta_type->isReference()) {
1961 meta_type->setTypeUsagePattern(AbstractMetaType::VariantPattern);
1961 meta_type->setTypeUsagePattern(AbstractMetaType::VariantPattern);
1962
1962
1963 } else if (type->isEnum() && meta_type->actualIndirections() == 0) {
1963 } else if (type->isEnum() && meta_type->actualIndirections() == 0) {
1964 meta_type->setTypeUsagePattern(AbstractMetaType::EnumPattern);
1964 meta_type->setTypeUsagePattern(AbstractMetaType::EnumPattern);
1965
1965
1966 } else if (type->isObject()
1966 } else if (type->isObject()
1967 && meta_type->indirections() == 0
1967 && meta_type->indirections() == 0
1968 && meta_type->isReference()) {
1968 && meta_type->isReference()) {
1969 if (((ComplexTypeEntry *) type)->isQObject())
1969 if (((ComplexTypeEntry *) type)->isQObject())
1970 meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
1970 meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
1971 else
1971 else
1972 meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
1972 meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
1973
1973
1974 } else if (type->isObject()
1974 } else if (type->isObject()
1975 && meta_type->indirections() == 1) {
1975 && meta_type->indirections() == 1) {
1976 if (((ComplexTypeEntry *) type)->isQObject())
1976 if (((ComplexTypeEntry *) type)->isQObject())
1977 meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
1977 meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
1978 else
1978 else
1979 meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
1979 meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
1980
1980
1981 // const-references to pointers can be passed as pointers
1981 // const-references to pointers can be passed as pointers
1982 if (meta_type->isReference() && meta_type->isConstant()) {
1982 if (meta_type->isReference() && meta_type->isConstant()) {
1983 meta_type->setReference(false);
1983 meta_type->setReference(false);
1984 meta_type->setConstant(false);
1984 meta_type->setConstant(false);
1985 }
1985 }
1986
1986
1987 } else if (type->isContainer() && meta_type->indirections() == 0) {
1987 } else if (type->isContainer() && meta_type->indirections() == 0) {
1988 meta_type->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
1988 meta_type->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
1989
1989
1990 } else if (type->isTemplateArgument()) {
1990 } else if (type->isTemplateArgument()) {
1991
1991
1992 } else if (type->isFlags()
1992 } else if (type->isFlags()
1993 && meta_type->indirections() == 0
1993 && meta_type->indirections() == 0
1994 && (meta_type->isConstant() == meta_type->isReference())) {
1994 && (meta_type->isConstant() == meta_type->isReference())) {
1995 meta_type->setTypeUsagePattern(AbstractMetaType::FlagsPattern);
1995 meta_type->setTypeUsagePattern(AbstractMetaType::FlagsPattern);
1996
1996
1997 } else if (type->isArray()) {
1997 } else if (type->isArray()) {
1998 meta_type->setTypeUsagePattern(AbstractMetaType::ArrayPattern);
1998 meta_type->setTypeUsagePattern(AbstractMetaType::ArrayPattern);
1999
1999
2000 } else if (type->isThread()) {
2000 } else if (type->isThread()) {
2001 Q_ASSERT(meta_type->indirections() == 1);
2001 Q_ASSERT(meta_type->indirections() == 1);
2002 meta_type->setTypeUsagePattern(AbstractMetaType::ThreadPattern);
2002 meta_type->setTypeUsagePattern(AbstractMetaType::ThreadPattern);
2003
2003
2004 } else if (type->isValue()
2004 } else if (type->isValue()
2005 && meta_type->indirections() == 0
2005 && meta_type->indirections() == 0
2006 && (meta_type->isConstant() == meta_type->isReference()
2006 && (meta_type->isConstant() == meta_type->isReference()
2007 || !meta_type->isReference())) {
2007 || !meta_type->isReference())) {
2008 meta_type->setTypeUsagePattern(AbstractMetaType::ValuePattern);
2008 meta_type->setTypeUsagePattern(AbstractMetaType::ValuePattern);
2009
2009
2010 } else {
2010 } else {
2011 meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
2011 meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
2012 ReportHandler::debugFull(QString("native pointer pattern for '%1'")
2012 ReportHandler::debugFull(QString("native pointer pattern for '%1'")
2013 .arg(meta_type->cppSignature()));
2013 .arg(meta_type->cppSignature()));
2014 }
2014 }
2015 }
2015 }
2016
2016
2017 QString AbstractMetaBuilder::translateDefaultValue(ArgumentModelItem item, AbstractMetaType *type,
2017 QString AbstractMetaBuilder::translateDefaultValue(ArgumentModelItem item, AbstractMetaType *type,
2018 AbstractMetaFunction *fnc, AbstractMetaClass *implementing_class,
2018 AbstractMetaFunction *fnc, AbstractMetaClass *implementing_class,
2019 int argument_index)
2019 int argument_index)
2020 {
2020 {
2021 QString function_name = fnc->name();
2021 QString function_name = fnc->name();
2022 QString class_name = implementing_class->name();
2022 QString class_name = implementing_class->name();
2023
2023
2024 QString replaced_expression = fnc->replacedDefaultExpression(implementing_class, argument_index + 1);
2024 QString replaced_expression = fnc->replacedDefaultExpression(implementing_class, argument_index + 1);
2025 if (fnc->removedDefaultExpression(implementing_class, argument_index +1))
2025 if (fnc->removedDefaultExpression(implementing_class, argument_index +1))
2026 return "";
2026 return "";
2027 if (!replaced_expression.isEmpty())
2027 if (!replaced_expression.isEmpty())
2028 return replaced_expression;
2028 return replaced_expression;
2029
2029
2030 QString expr = item->defaultValueExpression();
2030 QString expr = item->defaultValueExpression();
2031 if (type != 0 && type->isPrimitive()) {
2031 if (type != 0 && type->isPrimitive()) {
2032 if (type->name() == "boolean") {
2032 if (type->name() == "boolean") {
2033 if (expr == "false" || expr=="true") {
2033 if (expr == "false" || expr=="true") {
2034 return expr;
2034 return expr;
2035 } else {
2035 } else {
2036 bool ok = false;
2036 bool ok = false;
2037 int number = expr.toInt(&ok);
2037 int number = expr.toInt(&ok);
2038 if (ok && number)
2038 if (ok && number)
2039 return "true";
2039 return "true";
2040 else
2040 else
2041 return "false";
2041 return "false";
2042 }
2042 }
2043 } else if (expr == "ULONG_MAX") {
2043 } else if (expr == "ULONG_MAX") {
2044 return "Long.MAX_VALUE";
2044 return "Long.MAX_VALUE";
2045 } else if (expr == "QVariant::Invalid") {
2045 } else if (expr == "QVariant::Invalid") {
2046 return QString::number(QVariant::Invalid);
2046 return QString::number(QVariant::Invalid);
2047 } else {
2047 } else {
2048 // This can be an enum or flag so I need to delay the
2048 // This can be an enum or flag so I need to delay the
2049 // translation untill all namespaces are completly
2049 // translation untill all namespaces are completly
2050 // processed. This is done in figureOutEnumValues()
2050 // processed. This is done in figureOutEnumValues()
2051 return expr;
2051 return expr;
2052 }
2052 }
2053 } else if (type != 0 && (type->isFlags() || type->isEnum())) {
2053 } else if (type != 0 && (type->isFlags() || type->isEnum())) {
2054 // Same as with enum explanation above...
2054 // Same as with enum explanation above...
2055 return expr;
2055 return expr;
2056
2056
2057 } else {
2057 } else {
2058
2058
2059 // constructor or functioncall can be a bit tricky...
2059 // constructor or functioncall can be a bit tricky...
2060 if (expr == "QVariant()" || expr == "QModelIndex()") {
2060 if (expr == "QVariant()" || expr == "QModelIndex()") {
2061 return "null";
2061 return "null";
2062 } else if (expr == "QString()") {
2062 } else if (expr == "QString()") {
2063 return "null";
2063 return "null";
2064 } else if (expr.endsWith(")") && expr.contains("::")) {
2064 } else if (expr.endsWith(")") && expr.contains("::")) {
2065 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
2065 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
2066 if (typeEntry)
2066 if (typeEntry)
2067 return typeEntry->qualifiedTargetLangName() + "." + expr.right(expr.length() - expr.indexOf("::") - 2);
2067 return typeEntry->qualifiedTargetLangName() + "." + expr.right(expr.length() - expr.indexOf("::") - 2);
2068 } else if (expr.endsWith(")") && type != 0 && type->isValue()) {
2068 } else if (expr.endsWith(")") && type != 0 && type->isValue()) {
2069 int pos = expr.indexOf("(");
2069 int pos = expr.indexOf("(");
2070
2070
2071 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(pos));
2071 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(pos));
2072 if (typeEntry)
2072 if (typeEntry)
2073 return "new " + typeEntry->qualifiedTargetLangName() + expr.right(expr.length() - pos);
2073 return "new " + typeEntry->qualifiedTargetLangName() + expr.right(expr.length() - pos);
2074 else
2074 else
2075 return expr;
2075 return expr;
2076 } else if (expr == "0") {
2076 } else if (expr == "0") {
2077 return "null";
2077 return "null";
2078 } else if (type != 0 && (type->isObject() || type->isValue() || expr.contains("::"))) { // like Qt::black passed to a QColor
2078 } else if (type != 0 && (type->isObject() || type->isValue() || expr.contains("::"))) { // like Qt::black passed to a QColor
2079 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
2079 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
2080
2080
2081 expr = expr.right(expr.length() - expr.indexOf("::") - 2);
2081 expr = expr.right(expr.length() - expr.indexOf("::") - 2);
2082 if (typeEntry) {
2082 if (typeEntry) {
2083 return "new " + type->typeEntry()->qualifiedTargetLangName() +
2083 return "new " + type->typeEntry()->qualifiedTargetLangName() +
2084 "(" + typeEntry->qualifiedTargetLangName() + "." + expr + ")";
2084 "(" + typeEntry->qualifiedTargetLangName() + "." + expr + ")";
2085 }
2085 }
2086 }
2086 }
2087 }
2087 }
2088
2088
2089 QString warn = QString("unsupported default value '%3' of argument in function '%1', class '%2'")
2089 QString warn = QString("unsupported default value '%3' of argument in function '%1', class '%2'")
2090 .arg(function_name).arg(class_name).arg(item->defaultValueExpression());
2090 .arg(function_name).arg(class_name).arg(item->defaultValueExpression());
2091 ReportHandler::warning(warn);
2091 ReportHandler::warning(warn);
2092
2092
2093 return QString();
2093 return QString();
2094 }
2094 }
2095
2095
2096
2096
2097 bool AbstractMetaBuilder::isQObject(const QString &qualified_name)
2097 bool AbstractMetaBuilder::isQObject(const QString &qualified_name)
2098 {
2098 {
2099 if (qualified_name == "QObject")
2099 if (qualified_name == "QObject")
2100 return true;
2100 return true;
2101
2101
2102 ClassModelItem class_item = m_dom->findClass(qualified_name);
2102 ClassModelItem class_item = m_dom->findClass(qualified_name);
2103
2103
2104 if (!class_item) {
2104 if (!class_item) {
2105 QStringList names = qualified_name.split(QLatin1String("::"));
2105 QStringList names = qualified_name.split(QLatin1String("::"));
2106 NamespaceModelItem ns = model_dynamic_cast<NamespaceModelItem>(m_dom);
2106 NamespaceModelItem ns = model_dynamic_cast<NamespaceModelItem>(m_dom);
2107 for (int i=0; i<names.size() - 1 && ns; ++i)
2107 for (int i=0; i<names.size() - 1 && ns; ++i)
2108 ns = ns->namespaceMap().value(names.at(i));
2108 ns = ns->namespaceMap().value(names.at(i));
2109 if (ns && names.size() >= 2)
2109 if (ns && names.size() >= 2)
2110 class_item = ns->findClass(names.at(names.size() - 1));
2110 class_item = ns->findClass(names.at(names.size() - 1));
2111 }
2111 }
2112
2112
2113 bool isqobject = class_item && class_item->extendsClass("QObject");
2113 bool isqobject = class_item && class_item->extendsClass("QObject");
2114
2114
2115 if (class_item && !isqobject) {
2115 if (class_item && !isqobject) {
2116 QStringList baseClasses = class_item->baseClasses();
2116 QStringList baseClasses = class_item->baseClasses();
2117 for (int i=0; i<baseClasses.count(); ++i) {
2117 for (int i=0; i<baseClasses.count(); ++i) {
2118
2118
2119 isqobject = isQObject(baseClasses.at(i));
2119 isqobject = isQObject(baseClasses.at(i));
2120 if (isqobject)
2120 if (isqobject)
2121 break;
2121 break;
2122 }
2122 }
2123 }
2123 }
2124
2124
2125 return isqobject;
2125 return isqobject;
2126 }
2126 }
2127
2127
2128
2128
2129 bool AbstractMetaBuilder::isEnum(const QStringList &qualified_name)
2129 bool AbstractMetaBuilder::isEnum(const QStringList &qualified_name)
2130 {
2130 {
2131 CodeModelItem item = m_dom->model()->findItem(qualified_name, m_dom->toItem());
2131 CodeModelItem item = m_dom->model()->findItem(qualified_name, m_dom->toItem());
2132 return item && item->kind() == _EnumModelItem::__node_kind;
2132 return item && item->kind() == _EnumModelItem::__node_kind;
2133 }
2133 }
2134
2134
2135 AbstractMetaType *AbstractMetaBuilder::inheritTemplateType(const QList<AbstractMetaType *> &template_types,
2135 AbstractMetaType *AbstractMetaBuilder::inheritTemplateType(const QList<AbstractMetaType *> &template_types,
2136 AbstractMetaType *meta_type, bool *ok)
2136 AbstractMetaType *meta_type, bool *ok)
2137 {
2137 {
2138 if (ok != 0)
2138 if (ok != 0)
2139 *ok = true;
2139 *ok = true;
2140 if (!meta_type || (!meta_type->typeEntry()->isTemplateArgument() && !meta_type->hasInstantiations()))
2140 if (!meta_type || (!meta_type->typeEntry()->isTemplateArgument() && !meta_type->hasInstantiations()))
2141 return meta_type ? meta_type->copy() : 0;
2141 return meta_type ? meta_type->copy() : 0;
2142
2142
2143 AbstractMetaType *returned = meta_type->copy();
2143 AbstractMetaType *returned = meta_type->copy();
2144 returned->setOriginalTemplateType(meta_type->copy());
2144 returned->setOriginalTemplateType(meta_type->copy());
2145
2145
2146 if (returned->typeEntry()->isTemplateArgument()) {
2146 if (returned->typeEntry()->isTemplateArgument()) {
2147 const TemplateArgumentEntry *tae = static_cast<const TemplateArgumentEntry *>(returned->typeEntry());
2147 const TemplateArgumentEntry *tae = static_cast<const TemplateArgumentEntry *>(returned->typeEntry());
2148
2148
2149 // If the template is intantiated with void we special case this as rejecting the functions that use this
2149 // If the template is intantiated with void we special case this as rejecting the functions that use this
2150 // parameter from the instantiation.
2150 // parameter from the instantiation.
2151 if (template_types.size() <= tae->ordinal() || template_types.at(tae->ordinal())->typeEntry()->name() == "void") {
2151 if (template_types.size() <= tae->ordinal() || template_types.at(tae->ordinal())->typeEntry()->name() == "void") {
2152 if (ok != 0)
2152 if (ok != 0)
2153 *ok = false;
2153 *ok = false;
2154 return 0;
2154 return 0;
2155 }
2155 }
2156
2156
2157 AbstractMetaType *t = returned->copy();
2157 AbstractMetaType *t = returned->copy();
2158 t->setTypeEntry(template_types.at(tae->ordinal())->typeEntry());
2158 t->setTypeEntry(template_types.at(tae->ordinal())->typeEntry());
2159 t->setIndirections(template_types.at(tae->ordinal())->indirections() + t->indirections()
2159 t->setIndirections(template_types.at(tae->ordinal())->indirections() + t->indirections()
2160 ? 1
2160 ? 1
2161 : 0);
2161 : 0);
2162 decideUsagePattern(t);
2162 decideUsagePattern(t);
2163
2163
2164 delete returned;
2164 delete returned;
2165 returned = inheritTemplateType(template_types, t, ok);
2165 returned = inheritTemplateType(template_types, t, ok);
2166 if (ok != 0 && !(*ok))
2166 if (ok != 0 && !(*ok))
2167 return 0;
2167 return 0;
2168 }
2168 }
2169
2169
2170 if (returned->hasInstantiations()) {
2170 if (returned->hasInstantiations()) {
2171 QList<AbstractMetaType *> instantiations = returned->instantiations();
2171 QList<AbstractMetaType *> instantiations = returned->instantiations();
2172 for (int i=0; i<instantiations.count(); ++i) {
2172 for (int i=0; i<instantiations.count(); ++i) {
2173 instantiations[i] = inheritTemplateType(template_types, instantiations.at(i), ok);
2173 instantiations[i] = inheritTemplateType(template_types, instantiations.at(i), ok);
2174 if (ok != 0 && !(*ok))
2174 if (ok != 0 && !(*ok))
2175 return 0;
2175 return 0;
2176 }
2176 }
2177 returned->setInstantiations(instantiations);
2177 returned->setInstantiations(instantiations);
2178 }
2178 }
2179
2179
2180 return returned;
2180 return returned;
2181 }
2181 }
2182
2182
2183 bool AbstractMetaBuilder::inheritTemplate(AbstractMetaClass *subclass,
2183 bool AbstractMetaBuilder::inheritTemplate(AbstractMetaClass *subclass,
2184 const AbstractMetaClass *template_class,
2184 const AbstractMetaClass *template_class,
2185 const TypeParser::Info &info)
2185 const TypeParser::Info &info)
2186 {
2186 {
2187 QList<TypeParser::Info> targs = info.template_instantiations;
2187 QList<TypeParser::Info> targs = info.template_instantiations;
2188
2188
2189 QList<AbstractMetaType *> template_types;
2189 QList<AbstractMetaType *> template_types;
2190 foreach (const TypeParser::Info &i, targs) {
2190 foreach (const TypeParser::Info &i, targs) {
2191 TypeEntry *t = TypeDatabase::instance()->findType(i.qualified_name.join("::"));
2191 TypeEntry *t = TypeDatabase::instance()->findType(i.qualified_name.join("::"));
2192
2192
2193 if (t != 0) {
2193 if (t != 0) {
2194 AbstractMetaType *temporary_type = createMetaType();
2194 AbstractMetaType *temporary_type = createMetaType();
2195 temporary_type->setTypeEntry(t);
2195 temporary_type->setTypeEntry(t);
2196 temporary_type->setConstant(i.is_constant);
2196 temporary_type->setConstant(i.is_constant);
2197 temporary_type->setReference(i.is_reference);
2197 temporary_type->setReference(i.is_reference);
2198 temporary_type->setIndirections(i.indirections);
2198 temporary_type->setIndirections(i.indirections);
2199 template_types << temporary_type;
2199 template_types << temporary_type;
2200 }
2200 }
2201 }
2201 }
2202
2202
2203 AbstractMetaFunctionList funcs = subclass->functions();
2203 AbstractMetaFunctionList funcs = subclass->functions();
2204 foreach (const AbstractMetaFunction *function, template_class->functions()) {
2204 foreach (const AbstractMetaFunction *function, template_class->functions()) {
2205
2205
2206 if (function->isModifiedRemoved(TypeSystem::All))
2206 if (function->isModifiedRemoved(TypeSystem::All))
2207 continue;
2207 continue;
2208
2208
2209 AbstractMetaFunction *f = function->copy();
2209 AbstractMetaFunction *f = function->copy();
2210 f->setArguments(AbstractMetaArgumentList());
2210 f->setArguments(AbstractMetaArgumentList());
2211
2211
2212 bool ok = true;
2212 bool ok = true;
2213 AbstractMetaType *ftype = function->type();
2213 AbstractMetaType *ftype = function->type();
2214 f->setType(inheritTemplateType(template_types, ftype, &ok));
2214 f->setType(inheritTemplateType(template_types, ftype, &ok));
2215 if (!ok) {
2215 if (!ok) {
2216 delete f;
2216 delete f;
2217 continue;
2217 continue;
2218 }
2218 }
2219
2219
2220 foreach (AbstractMetaArgument *argument, function->arguments()) {
2220 foreach (AbstractMetaArgument *argument, function->arguments()) {
2221 AbstractMetaType *atype = argument->type();
2221 AbstractMetaType *atype = argument->type();
2222
2222
2223 AbstractMetaArgument *arg = argument->copy();
2223 AbstractMetaArgument *arg = argument->copy();
2224 arg->setType(inheritTemplateType(template_types, atype, &ok));
2224 arg->setType(inheritTemplateType(template_types, atype, &ok));
2225 if (!ok)
2225 if (!ok)
2226 break;
2226 break;
2227 f->addArgument(arg);
2227 f->addArgument(arg);
2228 }
2228 }
2229
2229
2230 if (!ok) {
2230 if (!ok) {
2231 delete f;
2231 delete f;
2232 continue ;
2232 continue ;
2233 }
2233 }
2234
2234
2235 // There is no base class in java to inherit from here, so the
2235 // There is no base class in java to inherit from here, so the
2236 // template instantiation is the class that implements the function..
2236 // template instantiation is the class that implements the function..
2237 f->setImplementingClass(subclass);
2237 f->setImplementingClass(subclass);
2238
2238
2239 // We also set it as the declaring class, since the superclass is
2239 // We also set it as the declaring class, since the superclass is
2240 // supposed to disappear. This allows us to make certain function modifications
2240 // supposed to disappear. This allows us to make certain function modifications
2241 // on the inherited functions.
2241 // on the inherited functions.
2242 f->setDeclaringClass(subclass);
2242 f->setDeclaringClass(subclass);
2243
2243
2244
2244
2245 if (f->isConstructor() && subclass->isTypeAlias()) {
2245 if (f->isConstructor() && subclass->isTypeAlias()) {
2246 f->setName(subclass->name());
2246 f->setName(subclass->name());
2247 } else if (f->isConstructor()) {
2247 } else if (f->isConstructor()) {
2248 delete f;
2248 delete f;
2249 continue;
2249 continue;
2250 }
2250 }
2251
2251
2252 // if the instantiation has a function named the same as an existing
2252 // if the instantiation has a function named the same as an existing
2253 // function we have shadowing so we need to skip it.
2253 // function we have shadowing so we need to skip it.
2254 bool found = false;
2254 bool found = false;
2255 for (int i=0; i<funcs.size(); ++i) {
2255 for (int i=0; i<funcs.size(); ++i) {
2256 if (funcs.at(i)->name() == f->name()) {
2256 if (funcs.at(i)->name() == f->name()) {
2257 found = true;
2257 found = true;
2258 continue;
2258 continue;
2259 }
2259 }
2260 }
2260 }
2261 if (found) {
2261 if (found) {
2262 delete f;
2262 delete f;
2263 continue;
2263 continue;
2264 }
2264 }
2265
2265
2266 ComplexTypeEntry *te = subclass->typeEntry();
2266 ComplexTypeEntry *te = subclass->typeEntry();
2267 FunctionModificationList mods = function->modifications(template_class);
2267 FunctionModificationList mods = function->modifications(template_class);
2268 for (int i=0; i<mods.size(); ++i) {
2268 for (int i=0; i<mods.size(); ++i) {
2269 FunctionModification mod = mods.at(i);
2269 FunctionModification mod = mods.at(i);
2270 mod.signature = f->minimalSignature();
2270 mod.signature = f->minimalSignature();
2271
2271
2272 // If we ever need it... Below is the code to do
2272 // If we ever need it... Below is the code to do
2273 // substitution of the template instantation type inside
2273 // substitution of the template instantation type inside
2274 // injected code..
2274 // injected code..
2275 #if 0
2275 #if 0
2276 if (mod.modifiers & Modification::CodeInjection) {
2276 if (mod.modifiers & Modification::CodeInjection) {
2277 for (int j=0; j<template_types.size(); ++j) {
2277 for (int j=0; j<template_types.size(); ++j) {
2278 CodeSnip &snip = mod.snips.last();
2278 CodeSnip &snip = mod.snips.last();
2279 QString code = snip.code();
2279 QString code = snip.code();
2280 code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j),
2280 code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j),
2281 template_types.at(j)->typeEntry()->qualifiedCppName());
2281 template_types.at(j)->typeEntry()->qualifiedCppName());
2282 snip.codeList.clear();
2282 snip.codeList.clear();
2283 snip.addCode(code);
2283 snip.addCode(code);
2284 }
2284 }
2285 }
2285 }
2286 #endif
2286 #endif
2287 te->addFunctionModification(mod);
2287 te->addFunctionModification(mod);
2288 }
2288 }
2289
2289
2290 subclass->addFunction(f);
2290 subclass->addFunction(f);
2291 }
2291 }
2292
2292
2293 // Clean up
2293 // Clean up
2294 foreach (AbstractMetaType *type, template_types) {
2294 foreach (AbstractMetaType *type, template_types) {
2295 delete type;
2295 delete type;
2296 }
2296 }
2297
2297
2298
2298
2299 {
2299 {
2300 subclass->setTemplateBaseClass(template_class);
2300 subclass->setTemplateBaseClass(template_class);
2301
2301
2302 subclass->setInterfaces(template_class->interfaces());
2302 subclass->setInterfaces(template_class->interfaces());
2303 subclass->setBaseClass(template_class->baseClass());
2303 subclass->setBaseClass(template_class->baseClass());
2304 }
2304 }
2305
2305
2306 return true;
2306 return true;
2307 }
2307 }
2308
2308
2309 void AbstractMetaBuilder::parseQ_Property(AbstractMetaClass *meta_class, const QStringList &declarations)
2309 void AbstractMetaBuilder::parseQ_Property(AbstractMetaClass *meta_class, const QStringList &declarations)
2310 {
2310 {
2311 for (int i=0; i<declarations.size(); ++i) {
2311 for (int i=0; i<declarations.size(); ++i) {
2312 QString p = declarations.at(i);
2312 QString p = declarations.at(i);
2313
2313
2314 QStringList l = p.split(QLatin1String(" "));
2314 QStringList l = p.split(QLatin1String(" "));
2315
2315
2316
2316
2317 QStringList qualifiedScopeName = currentScope()->qualifiedName();
2317 QStringList qualifiedScopeName = currentScope()->qualifiedName();
2318 bool ok = false;
2318 bool ok = false;
2319 AbstractMetaType *type = 0;
2319 AbstractMetaType *type = 0;
2320 QString scope;
2320 QString scope;
2321 for (int j=qualifiedScopeName.size(); j>=0; --j) {
2321 for (int j=qualifiedScopeName.size(); j>=0; --j) {
2322 scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join("::") + "::" : QString();
2322 scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join("::") + "::" : QString();
2323 TypeInfo info;
2323 TypeInfo info;
2324 info.setQualifiedName((scope + l.at(0)).split("::"));
2324 info.setQualifiedName((scope + l.at(0)).split("::"));
2325
2325
2326 type = translateType(info, &ok);
2326 type = translateType(info, &ok);
2327 if (type != 0 && ok) {
2327 if (type != 0 && ok) {
2328 break;
2328 break;
2329 }
2329 }
2330 }
2330 }
2331
2331
2332 if (type == 0 || !ok) {
2332 if (type == 0 || !ok) {
2333 ReportHandler::warning(QString("Unable to decide type of property: '%1' in class '%2'")
2333 ReportHandler::warning(QString("Unable to decide type of property: '%1' in class '%2'")
2334 .arg(l.at(0)).arg(meta_class->name()));
2334 .arg(l.at(0)).arg(meta_class->name()));
2335 continue;
2335 continue;
2336 }
2336 }
2337
2337
2338 QString typeName = scope + l.at(0);
2338 QString typeName = scope + l.at(0);
2339
2339
2340 QPropertySpec *spec = new QPropertySpec(type->typeEntry());
2340 QPropertySpec *spec = new QPropertySpec(type->typeEntry());
2341 spec->setName(l.at(1));
2341 spec->setName(l.at(1));
2342 spec->setIndex(i);
2342 spec->setIndex(i);
2343
2343
2344 for (int pos=2; pos+1<l.size(); pos+=2) {
2344 for (int pos=2; pos+1<l.size(); pos+=2) {
2345 if (l.at(pos) == QLatin1String("READ"))
2345 if (l.at(pos) == QLatin1String("READ"))
2346 spec->setRead(l.at(pos+1));
2346 spec->setRead(l.at(pos+1));
2347 else if (l.at(pos) == QLatin1String("WRITE"))
2347 else if (l.at(pos) == QLatin1String("WRITE"))
2348 spec->setWrite(l.at(pos+1));
2348 spec->setWrite(l.at(pos+1));
2349 else if (l.at(pos) == QLatin1String("DESIGNABLE"))
2349 else if (l.at(pos) == QLatin1String("DESIGNABLE"))
2350 spec->setDesignable(l.at(pos+1));
2350 spec->setDesignable(l.at(pos+1));
2351 else if (l.at(pos) == QLatin1String("RESET"))
2351 else if (l.at(pos) == QLatin1String("RESET"))
2352 spec->setReset(l.at(pos+1));
2352 spec->setReset(l.at(pos+1));
2353 }
2353 }
2354
2354
2355 meta_class->addPropertySpec(spec);
2355 meta_class->addPropertySpec(spec);
2356 delete type;
2356 delete type;
2357 }
2357 }
2358 }
2358 }
2359
2359
2360 static void hide_functions(const AbstractMetaFunctionList &l) {
2360 static void hide_functions(const AbstractMetaFunctionList &l) {
2361 foreach (AbstractMetaFunction *f, l) {
2361 foreach (AbstractMetaFunction *f, l) {
2362 FunctionModification mod;
2362 FunctionModification mod;
2363 mod.signature = f->minimalSignature();
2363 mod.signature = f->minimalSignature();
2364 mod.modifiers = FunctionModification::Private;
2364 mod.modifiers = FunctionModification::Private;
2365 ((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
2365 ((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
2366 }
2366 }
2367 }
2367 }
2368
2368
2369 static void remove_function(AbstractMetaFunction *f) {
2369 static void remove_function(AbstractMetaFunction *f) {
2370 FunctionModification mod;
2370 FunctionModification mod;
2371 mod.removal = TypeSystem::All;
2371 mod.removal = TypeSystem::All;
2372 mod.signature = f->minimalSignature();
2372 mod.signature = f->minimalSignature();
2373 ((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
2373 ((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
2374 }
2374 }
2375
2375
2376 static AbstractMetaFunctionList filter_functions(const AbstractMetaFunctionList &lst, QSet<QString> *signatures)
2376 static AbstractMetaFunctionList filter_functions(const AbstractMetaFunctionList &lst, QSet<QString> *signatures)
2377 {
2377 {
2378 AbstractMetaFunctionList functions;
2378 AbstractMetaFunctionList functions;
2379 foreach (AbstractMetaFunction *f, lst) {
2379 foreach (AbstractMetaFunction *f, lst) {
2380 QString signature = f->minimalSignature();
2380 QString signature = f->minimalSignature();
2381 int start = signature.indexOf(QLatin1Char('(')) + 1;
2381 int start = signature.indexOf(QLatin1Char('(')) + 1;
2382 int end = signature.lastIndexOf(QLatin1Char(')'));
2382 int end = signature.lastIndexOf(QLatin1Char(')'));
2383 signature = signature.mid(start, end - start);
2383 signature = signature.mid(start, end - start);
2384 if (signatures->contains(signature)) {
2384 if (signatures->contains(signature)) {
2385 remove_function(f);
2385 remove_function(f);
2386 continue;
2386 continue;
2387 }
2387 }
2388 (*signatures) << signature;
2388 (*signatures) << signature;
2389 functions << f;
2389 functions << f;
2390 }
2390 }
2391 return functions;
2391 return functions;
2392 }
2392 }
2393
2393
2394 void AbstractMetaBuilder::setupEquals(AbstractMetaClass *cls)
2394 void AbstractMetaBuilder::setupEquals(AbstractMetaClass *cls)
2395 {
2395 {
2396 AbstractMetaFunctionList equals;
2396 AbstractMetaFunctionList equals;
2397 AbstractMetaFunctionList nequals;
2397 AbstractMetaFunctionList nequals;
2398
2398
2399 QString op_equals = QLatin1String("operator_equal");
2399 QString op_equals = QLatin1String("operator_equal");
2400 QString op_nequals = QLatin1String("operator_not_equal");
2400 QString op_nequals = QLatin1String("operator_not_equal");
2401
2401
2402 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
2402 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
2403 | AbstractMetaClass::NotRemovedFromTargetLang);
2403 | AbstractMetaClass::NotRemovedFromTargetLang);
2404 foreach (AbstractMetaFunction *f, functions) {
2404 foreach (AbstractMetaFunction *f, functions) {
2405 if (f->name() == op_equals)
2405 if (f->name() == op_equals)
2406 equals << f;
2406 equals << f;
2407 else if (f->name() == op_nequals)
2407 else if (f->name() == op_nequals)
2408 nequals << f;
2408 nequals << f;
2409 }
2409 }
2410
2410
2411 if (equals.size() || nequals.size()) {
2411 if (equals.size() || nequals.size()) {
2412 if (!cls->hasHashFunction()) {
2412 if (!cls->hasHashFunction()) {
2413 ReportHandler::warning(QString::fromLatin1("Class '%1' has equals operators but no qHash() function")
2413 ReportHandler::warning(QString::fromLatin1("Class '%1' has equals operators but no qHash() function")
2414 .arg(cls->name()));
2414 .arg(cls->name()));
2415 }
2415 }
2416
2416
2417 hide_functions(equals);
2417 hide_functions(equals);
2418 hide_functions(nequals);
2418 hide_functions(nequals);
2419
2419
2420 // We only need == if we have both == and !=, and one == for
2420 // We only need == if we have both == and !=, and one == for
2421 // each signature type, like QDateTime::==(QDate) and (QTime)
2421 // each signature type, like QDateTime::==(QDate) and (QTime)
2422 // if such a thing exists...
2422 // if such a thing exists...
2423 QSet<QString> func_signatures;
2423 QSet<QString> func_signatures;
2424 cls->setEqualsFunctions(filter_functions(equals, &func_signatures));
2424 cls->setEqualsFunctions(filter_functions(equals, &func_signatures));
2425 cls->setNotEqualsFunctions(filter_functions(nequals, &func_signatures));
2425 cls->setNotEqualsFunctions(filter_functions(nequals, &func_signatures));
2426 }
2426 }
2427 }
2427 }
2428
2428
2429 void AbstractMetaBuilder::setupComparable(AbstractMetaClass *cls)
2429 void AbstractMetaBuilder::setupComparable(AbstractMetaClass *cls)
2430 {
2430 {
2431 AbstractMetaFunctionList greater;
2431 AbstractMetaFunctionList greater;
2432 AbstractMetaFunctionList greaterEquals;
2432 AbstractMetaFunctionList greaterEquals;
2433 AbstractMetaFunctionList less;
2433 AbstractMetaFunctionList less;
2434 AbstractMetaFunctionList lessEquals;
2434 AbstractMetaFunctionList lessEquals;
2435
2435
2436 QString op_greater = QLatin1String("operator_greater");
2436 QString op_greater = QLatin1String("operator_greater");
2437 QString op_greater_eq = QLatin1String("operator_greater_or_equal");
2437 QString op_greater_eq = QLatin1String("operator_greater_or_equal");
2438 QString op_less = QLatin1String("operator_less");
2438 QString op_less = QLatin1String("operator_less");
2439 QString op_less_eq = QLatin1String("operator_less_or_equal");
2439 QString op_less_eq = QLatin1String("operator_less_or_equal");
2440
2440
2441 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
2441 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
2442 | AbstractMetaClass::NotRemovedFromTargetLang);
2442 | AbstractMetaClass::NotRemovedFromTargetLang);
2443 foreach (AbstractMetaFunction *f, functions) {
2443 foreach (AbstractMetaFunction *f, functions) {
2444 if (f->name() == op_greater)
2444 if (f->name() == op_greater)
2445 greater << f;
2445 greater << f;
2446 else if (f->name() == op_greater_eq)
2446 else if (f->name() == op_greater_eq)
2447 greaterEquals << f;
2447 greaterEquals << f;
2448 else if (f->name() == op_less)
2448 else if (f->name() == op_less)
2449 less << f;
2449 less << f;
2450 else if (f->name() == op_less_eq)
2450 else if (f->name() == op_less_eq)
2451 lessEquals << f;
2451 lessEquals << f;
2452 }
2452 }
2453
2453
2454 bool hasEquals = cls->equalsFunctions().size() || cls->notEqualsFunctions().size();
2454 bool hasEquals = cls->equalsFunctions().size() || cls->notEqualsFunctions().size();
2455
2455
2456 // Conditions for comparable is:
2456 // Conditions for comparable is:
2457 // >, ==, < - The basic case
2457 // >, ==, < - The basic case
2458 // >, == - Less than becomes else case
2458 // >, == - Less than becomes else case
2459 // <, == - Greater than becomes else case
2459 // <, == - Greater than becomes else case
2460 // >=, <= - if (<= && >=) -> equal
2460 // >=, <= - if (<= && >=) -> equal
2461 bool mightBeComparable = greater.size() || greaterEquals.size() || less.size() || lessEquals.size()
2461 bool mightBeComparable = greater.size() || greaterEquals.size() || less.size() || lessEquals.size()
2462 || greaterEquals.size() == 1 || lessEquals.size() == 1;
2462 || greaterEquals.size() == 1 || lessEquals.size() == 1;
2463
2463
2464 if (mightBeComparable) {
2464 if (mightBeComparable) {
2465 QSet<QString> signatures;
2465 QSet<QString> signatures;
2466
2466
2467 // We only hide the original functions if we are able to make a compareTo() method
2467 // We only hide the original functions if we are able to make a compareTo() method
2468 bool wasComparable = false;
2468 bool wasComparable = false;
2469
2469
2470 // The three upper cases, prefer the <, == approach
2470 // The three upper cases, prefer the <, == approach
2471 if (hasEquals && (greater.size() || less.size())) {
2471 if (hasEquals && (greater.size() || less.size())) {
2472 cls->setLessThanFunctions(filter_functions(less, &signatures));
2472 cls->setLessThanFunctions(filter_functions(less, &signatures));
2473 cls->setGreaterThanFunctions(filter_functions(greater, &signatures));
2473 cls->setGreaterThanFunctions(filter_functions(greater, &signatures));
2474 filter_functions(greaterEquals, &signatures);
2474 filter_functions(greaterEquals, &signatures);
2475 filter_functions(lessEquals, &signatures);
2475 filter_functions(lessEquals, &signatures);
2476 wasComparable = true;
2476 wasComparable = true;
2477 } else if (hasEquals && (greaterEquals.size() || lessEquals.size())) {
2477 } else if (hasEquals && (greaterEquals.size() || lessEquals.size())) {
2478 cls->setLessThanEqFunctions(filter_functions(lessEquals, &signatures));
2478 cls->setLessThanEqFunctions(filter_functions(lessEquals, &signatures));
2479 cls->setGreaterThanEqFunctions(filter_functions(greaterEquals, &signatures));
2479 cls->setGreaterThanEqFunctions(filter_functions(greaterEquals, &signatures));
2480 wasComparable = true;
2480 wasComparable = true;
2481 } else if (greaterEquals.size() == 1 || lessEquals.size() == 1) {
2481 } else if (greaterEquals.size() == 1 || lessEquals.size() == 1) {
2482 cls->setGreaterThanEqFunctions(greaterEquals);
2482 cls->setGreaterThanEqFunctions(greaterEquals);
2483 cls->setLessThanEqFunctions(lessEquals);
2483 cls->setLessThanEqFunctions(lessEquals);
2484 filter_functions(less, &signatures);
2484 filter_functions(less, &signatures);
2485 filter_functions(greater, &signatures);
2485 filter_functions(greater, &signatures);
2486 wasComparable = true;
2486 wasComparable = true;
2487 }
2487 }
2488
2488
2489 if (wasComparable) {
2489 if (wasComparable) {
2490 hide_functions(greater);
2490 hide_functions(greater);
2491 hide_functions(greaterEquals);
2491 hide_functions(greaterEquals);
2492 hide_functions(less);
2492 hide_functions(less);
2493 hide_functions(lessEquals);
2493 hide_functions(lessEquals);
2494 }
2494 }
2495 }
2495 }
2496
2496
2497 }
2497 }
2498
2498
2499 void AbstractMetaBuilder::setupClonable(AbstractMetaClass *cls)
2499 void AbstractMetaBuilder::setupClonable(AbstractMetaClass *cls)
2500 {
2500 {
2501 QString op_assign = QLatin1String("operator_assign");
2501 QString op_assign = QLatin1String("operator_assign");
2502
2502
2503 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements);
2503 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements);
2504 foreach (AbstractMetaFunction *f, functions) {
2504 foreach (AbstractMetaFunction *f, functions) {
2505 if ((f->name() == op_assign || f->isConstructor()) && f->isPublic()) {
2505 if ((f->name() == op_assign || f->isConstructor()) && f->isPublic()) {
2506 AbstractMetaArgumentList arguments = f->arguments();
2506 AbstractMetaArgumentList arguments = f->arguments();
2507 if (arguments.size() == 1) {
2507 if (arguments.size() == 1) {
2508 if (cls->typeEntry()->qualifiedCppName() == arguments.at(0)->type()->typeEntry()->qualifiedCppName()) {
2508 if (cls->typeEntry()->qualifiedCppName() == arguments.at(0)->type()->typeEntry()->qualifiedCppName()) {
2509 if (cls->typeEntry()->isValue()) {
2509 if (cls->typeEntry()->isValue()) {
2510 cls->setHasCloneOperator(true);
2510 cls->setHasCloneOperator(true);
2511 return;
2511 return;
2512 }
2512 }
2513 }
2513 }
2514 }
2514 }
2515 }
2515 }
2516 }
2516 }
2517 }
2517 }
2518
2518
2519 static void write_reject_log_file(const QString &name,
2519 static void write_reject_log_file(const QString &name,
2520 const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects)
2520 const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects)
2521 {
2521 {
2522 QFile f(name);
2522 QFile f(name);
2523 if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
2523 if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
2524 ReportHandler::warning(QString("failed to write log file: '%1'")
2524 ReportHandler::warning(QString("failed to write log file: '%1'")
2525 .arg(f.fileName()));
2525 .arg(f.fileName()));
2526 return;
2526 return;
2527 }
2527 }
2528
2528
2529 QTextStream s(&f);
2529 QTextStream s(&f);
2530
2530
2531
2531
2532 for (int reason=0; reason<AbstractMetaBuilder::NoReason; ++reason) {
2532 for (int reason=0; reason<AbstractMetaBuilder::NoReason; ++reason) {
2533 s << QString(72, '*') << endl;
2533 s << QString(72, '*') << endl;
2534 switch (reason) {
2534 switch (reason) {
2535 case AbstractMetaBuilder::NotInTypeSystem:
2535 case AbstractMetaBuilder::NotInTypeSystem:
2536 s << "Not in type system";
2536 s << "Not in type system";
2537 break;
2537 break;
2538 case AbstractMetaBuilder::GenerationDisabled:
2538 case AbstractMetaBuilder::GenerationDisabled:
2539 s << "Generation disabled by type system";
2539 s << "Generation disabled by type system";
2540 break;
2540 break;
2541 case AbstractMetaBuilder::RedefinedToNotClass:
2541 case AbstractMetaBuilder::RedefinedToNotClass:
2542 s << "Type redefined to not be a class";
2542 s << "Type redefined to not be a class";
2543 break;
2543 break;
2544
2544
2545 case AbstractMetaBuilder::UnmatchedReturnType:
2545 case AbstractMetaBuilder::UnmatchedReturnType:
2546 s << "Unmatched return type";
2546 s << "Unmatched return type";
2547 break;
2547 break;
2548
2548
2549 case AbstractMetaBuilder::UnmatchedArgumentType:
2549 case AbstractMetaBuilder::UnmatchedArgumentType:
2550 s << "Unmatched argument type";
2550 s << "Unmatched argument type";
2551 break;
2551 break;
2552
2552
2553 default:
2553 default:
2554 s << "unknown reason";
2554 s << "unknown reason";
2555 break;
2555 break;
2556 }
2556 }
2557
2557
2558 s << endl;
2558 s << endl;
2559
2559
2560 for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin();
2560 for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin();
2561 it != rejects.constEnd(); ++it) {
2561 it != rejects.constEnd(); ++it) {
2562 if (it.value() != reason)
2562 if (it.value() != reason)
2563 continue;
2563 continue;
2564 s << " - " << it.key() << endl;
2564 s << " - " << it.key() << endl;
2565 }
2565 }
2566
2566
2567 s << QString(72, '*') << endl << endl;
2567 s << QString(72, '*') << endl << endl;
2568 }
2568 }
2569
2569
2570 }
2570 }
2571
2571
2572
2572
2573 void AbstractMetaBuilder::dumpLog()
2573 void AbstractMetaBuilder::dumpLog()
2574 {
2574 {
2575 write_reject_log_file("mjb_rejected_classes.log", m_rejected_classes);
2575 write_reject_log_file("mjb_rejected_classes.log", m_rejected_classes);
2576 write_reject_log_file("mjb_rejected_enums.log", m_rejected_enums);
2576 write_reject_log_file("mjb_rejected_enums.log", m_rejected_enums);
2577 write_reject_log_file("mjb_rejected_functions.log", m_rejected_functions);
2577 write_reject_log_file("mjb_rejected_functions.log", m_rejected_functions);
2578 write_reject_log_file("mjb_rejected_fields.log", m_rejected_fields);
2578 write_reject_log_file("mjb_rejected_fields.log", m_rejected_fields);
2579 }
2579 }
2580
2580
2581 AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted() const
2581 AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted() const
2582 {
2582 {
2583 AbstractMetaClassList res;
2583 AbstractMetaClassList res;
2584
2584
2585 AbstractMetaClassList classes = m_meta_classes;
2585 AbstractMetaClassList classes = m_meta_classes;
2586 qSort(classes);
2586 qSort(classes);
2587
2587
2588 QSet<AbstractMetaClass*> noDependency;
2588 QSet<AbstractMetaClass*> noDependency;
2589 QHash<AbstractMetaClass*, QSet<AbstractMetaClass* >* > hash;
2589 QHash<AbstractMetaClass*, QSet<AbstractMetaClass* >* > hash;
2590 foreach (AbstractMetaClass *cls, classes) {
2590 foreach (AbstractMetaClass *cls, classes) {
2591 QSet<AbstractMetaClass* > *depends = new QSet<AbstractMetaClass* >();
2591 QSet<AbstractMetaClass* > *depends = new QSet<AbstractMetaClass* >();
2592
2592
2593 if (cls->baseClass())
2593 if (cls->baseClass())
2594 depends->insert(cls->baseClass());
2594 depends->insert(cls->baseClass());
2595
2595
2596 foreach (AbstractMetaClass *interface, cls->interfaces()) {
2596 foreach (AbstractMetaClass *interface, cls->interfaces()) {
2597 AbstractMetaClass *impl = interface->primaryInterfaceImplementor();
2597 AbstractMetaClass *impl = interface->primaryInterfaceImplementor();
2598 if (impl == cls)
2598 if (impl == cls)
2599 continue;
2599 continue;
2600 depends->insert(impl);
2600 depends->insert(impl);
2601 }
2601 }
2602
2602
2603 if (depends->empty()) {
2603 if (depends->empty()) {
2604 noDependency.insert(cls);
2604 noDependency.insert(cls);
2605 } else {
2605 } else {
2606 hash.insert(cls, depends);
2606 hash.insert(cls, depends);
2607 }
2607 }
2608 }
2608 }
2609
2609
2610 while (!noDependency.empty()) {
2610 while (!noDependency.empty()) {
2611 foreach (AbstractMetaClass *cls, noDependency.values()) {
2611 foreach (AbstractMetaClass *cls, noDependency.values()) {
2612 if(!cls->isInterface())
2612 if(!cls->isInterface())
2613 res.append(cls);
2613 res.append(cls);
2614 noDependency.remove(cls);
2614 noDependency.remove(cls);
2615 QHashIterator<AbstractMetaClass*, QSet<AbstractMetaClass* >* > i(hash);
2615 QHashIterator<AbstractMetaClass*, QSet<AbstractMetaClass* >* > i(hash);
2616 while (i.hasNext()) {
2616 while (i.hasNext()) {
2617 i.next();
2617 i.next();
2618 i.value()->remove(cls);
2618 i.value()->remove(cls);
2619 if (i.value()->empty()) {
2619 if (i.value()->empty()) {
2620 AbstractMetaClass *key = i.key();
2620 AbstractMetaClass *key = i.key();
2621 noDependency.insert(key);
2621 noDependency.insert(key);
2622 hash.remove(key);
2622 hash.remove(key);
2623 delete(i.value());
2623 delete(i.value());
2624 }
2624 }
2625 }
2625 }
2626 }
2626 }
2627 }
2627 }
2628
2628
2629 if (!noDependency.empty() || !hash.empty()) {
2629 if (!noDependency.empty() || !hash.empty()) {
2630 qWarning("dependency graph was cyclic.");
2630 qWarning("dependency graph was cyclic.");
2631 }
2631 }
2632
2632
2633 return res;
2633 return res;
2634 }
2634 }
@@ -1,48 +1,48
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #include "metaqtscript.h"
42 #include "metaqtscript.h"
43
43
44
44
45 bool MetaQtScriptClass::hasDefaultToStringFunction() const
45 bool MetaQtScriptClass::hasDefaultToStringFunction() const
46 {
46 {
47 return 0 < queryFunctionsByName("toString").size();
47 return AbstractMetaClass::hasDefaultToStringFunction();
48 }
48 }
@@ -1,379 +1,379
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #include "shellgenerator.h"
42 #include "shellgenerator.h"
43 #include "reporthandler.h"
43 #include "reporthandler.h"
44
44
45 #include "metaqtscript.h"
45 #include "metaqtscript.h"
46
46
47 bool ShellGenerator::shouldGenerate(const AbstractMetaClass *meta_class) const
47 bool ShellGenerator::shouldGenerate(const AbstractMetaClass *meta_class) const
48 {
48 {
49 uint cg = meta_class->typeEntry()->codeGeneration();
49 uint cg = meta_class->typeEntry()->codeGeneration();
50 if (meta_class->name().startsWith("QtScript")) return false;
50 if (meta_class->name().startsWith("QtScript")) return false;
51 if (meta_class->name().startsWith("QFuture")) return false;
51 if (meta_class->name().startsWith("QFuture")) return false;
52 if (meta_class->name().startsWith("Global")) return false;
52 if (meta_class->name().startsWith("Global")) return false;
53 if (meta_class->name().startsWith("QStyleOptionComplex")) return false;
53 if (meta_class->name().startsWith("QStyleOptionComplex")) return false;
54 if (meta_class->name().startsWith("QTextLayout")) return false;
54 if (meta_class->name().startsWith("QTextLayout")) return false;
55 if (meta_class->name().startsWith("QPersistentModelIndex")) return false;
55 if (meta_class->name().startsWith("QPersistentModelIndex")) return false;
56 return ((cg & TypeEntry::GenerateCode) != 0);
56 return ((cg & TypeEntry::GenerateCode) != 0);
57 }
57 }
58
58
59 void ShellGenerator::writeTypeInfo(QTextStream &s, const AbstractMetaType *type, Option options)
59 void ShellGenerator::writeTypeInfo(QTextStream &s, const AbstractMetaType *type, Option options)
60 {
60 {
61 if ((options & OriginalTypeDescription) && !type->originalTypeDescription().isEmpty()) {
61 if ((options & OriginalTypeDescription) && !type->originalTypeDescription().isEmpty()) {
62 s << type->originalTypeDescription();
62 s << type->originalTypeDescription();
63 return;
63 return;
64 }
64 }
65
65
66 if (type->isArray()) {
66 if (type->isArray()) {
67 writeTypeInfo(s, type->arrayElementType(), options);
67 writeTypeInfo(s, type->arrayElementType(), options);
68 if (options & ArrayAsPointer) {
68 if (options & ArrayAsPointer) {
69 s << "*";
69 s << "*";
70 } else {
70 } else {
71 s << "[" << type->arrayElementCount() << "]";
71 s << "[" << type->arrayElementCount() << "]";
72 }
72 }
73 return;
73 return;
74 }
74 }
75
75
76 const TypeEntry *te = type->typeEntry();
76 const TypeEntry *te = type->typeEntry();
77
77
78 if (type->isConstant() && !(options & ExcludeConst))
78 if (type->isConstant() && !(options & ExcludeConst))
79 s << "const ";
79 s << "const ";
80
80
81 if ((options & EnumAsInts) && (te->isEnum() || te->isFlags())) {
81 if ((options & EnumAsInts) && (te->isEnum() || te->isFlags())) {
82 s << "int";
82 s << "int";
83 } else if (te->isFlags()) {
83 } else if (te->isFlags()) {
84 s << ((FlagsTypeEntry *) te)->originalName();
84 s << ((FlagsTypeEntry *) te)->originalName();
85 } else {
85 } else {
86 s << fixCppTypeName(te->qualifiedCppName());
86 s << fixCppTypeName(te->qualifiedCppName());
87 }
87 }
88
88
89 if (type->instantiations().size() > 0
89 if (type->instantiations().size() > 0
90 && (!type->isContainer()
90 && (!type->isContainer()
91 || (static_cast<const ContainerTypeEntry *>(te))->type() != ContainerTypeEntry::StringListContainer)) {
91 || (static_cast<const ContainerTypeEntry *>(te))->type() != ContainerTypeEntry::StringListContainer)) {
92 s << '<';
92 s << '<';
93 QList<AbstractMetaType *> args = type->instantiations();
93 QList<AbstractMetaType *> args = type->instantiations();
94 bool nested_template = false;
94 bool nested_template = false;
95 for (int i=0; i<args.size(); ++i) {
95 for (int i=0; i<args.size(); ++i) {
96 if (i != 0)
96 if (i != 0)
97 s << ", ";
97 s << ", ";
98 nested_template |= args.at(i)->isContainer();
98 nested_template |= args.at(i)->isContainer();
99 writeTypeInfo(s, args.at(i));
99 writeTypeInfo(s, args.at(i));
100 }
100 }
101 if (nested_template)
101 if (nested_template)
102 s << ' ';
102 s << ' ';
103 s << '>';
103 s << '>';
104 }
104 }
105
105
106 s << QString(type->indirections(), '*');
106 s << QString(type->indirections(), '*');
107
107
108 if (type->isReference() && !(options & ExcludeReference) && !(options & ConvertReferenceToPtr))
108 if (type->isReference() && !(options & ExcludeReference) && !(options & ConvertReferenceToPtr))
109 s << "&";
109 s << "&";
110
110
111 if (type->isReference() && (options & ConvertReferenceToPtr)) {
111 if (type->isReference() && (options & ConvertReferenceToPtr)) {
112 s << "*";
112 s << "*";
113 }
113 }
114
114
115
115
116 if (!(options & SkipName))
116 if (!(options & SkipName))
117 s << ' ';
117 s << ' ';
118 }
118 }
119
119
120
120
121 void ShellGenerator::writeFunctionArguments(QTextStream &s, const AbstractMetaClass* owner,
121 void ShellGenerator::writeFunctionArguments(QTextStream &s, const AbstractMetaClass* owner,
122 const AbstractMetaArgumentList &arguments,
122 const AbstractMetaArgumentList &arguments,
123 Option option,
123 Option option,
124 int numArguments)
124 int numArguments)
125 {
125 {
126 if (numArguments < 0) numArguments = arguments.size();
126 if (numArguments < 0) numArguments = arguments.size();
127
127
128 for (int i=0; i<numArguments; ++i) {
128 for (int i=0; i<numArguments; ++i) {
129 if (i != 0)
129 if (i != 0)
130 s << ", ";
130 s << ", ";
131 AbstractMetaArgument *arg = arguments.at(i);
131 AbstractMetaArgument *arg = arguments.at(i);
132 writeTypeInfo(s, arg->type(), option);
132 writeTypeInfo(s, arg->type(), option);
133 if (!(option & SkipName))
133 if (!(option & SkipName))
134 s << " " << arg->argumentName();
134 s << " " << arg->argumentName();
135 if ((option & IncludeDefaultExpression) && !arg->originalDefaultValueExpression().isEmpty()) {
135 if ((option & IncludeDefaultExpression) && !arg->originalDefaultValueExpression().isEmpty()) {
136 s << " = ";
136 s << " = ";
137
137
138 QString expr = arg->originalDefaultValueExpression();
138 QString expr = arg->originalDefaultValueExpression();
139 if (expr != "0") {
139 if (expr != "0") {
140 QString qualifier;
140 QString qualifier;
141 if (arg->type()->typeEntry()->isEnum() && expr.indexOf("::") < 0) {
141 if (arg->type()->typeEntry()->isEnum() && expr.indexOf("::") < 0) {
142 qualifier = ((EnumTypeEntry *)arg->type()->typeEntry())->qualifier();
142 qualifier = ((EnumTypeEntry *)arg->type()->typeEntry())->qualifier();
143 } else if (arg->type()->typeEntry()->isFlags() && expr.indexOf("::") < 0) {
143 } else if (arg->type()->typeEntry()->isFlags() && expr.indexOf("::") < 0) {
144 qualifier = ((FlagsTypeEntry *)arg->type()->typeEntry())->originator()->qualifier();
144 qualifier = ((FlagsTypeEntry *)arg->type()->typeEntry())->originator()->qualifier();
145 }
145 }
146 if (!qualifier.isEmpty()) {
146 if (!qualifier.isEmpty()) {
147 s << qualifier << "::";
147 s << qualifier << "::";
148 }
148 }
149 }
149 }
150 if (expr.contains("defaultConnection")) {
150 if (expr.contains("defaultConnection")) {
151 expr.replace("defaultConnection","QSqlDatabase::defaultConnection");
151 expr.replace("defaultConnection","QSqlDatabase::defaultConnection");
152 }
152 }
153 if (expr == "MediaSource()") {
153 if (expr == "MediaSource()") {
154 expr = "Phonon::MediaSource()";
154 expr = "Phonon::MediaSource()";
155 }
155 }
156 s << expr;
156 s << expr;
157 }
157 }
158 }
158 }
159 }
159 }
160
160
161 /*!
161 /*!
162 * Writes the function \a meta_function signature to the textstream \a s.
162 * Writes the function \a meta_function signature to the textstream \a s.
163 *
163 *
164 * The \a name_prefix can be used to give the function name a prefix,
164 * The \a name_prefix can be used to give the function name a prefix,
165 * like "__public_" or "__override_" and \a classname_prefix can
165 * like "__public_" or "__override_" and \a classname_prefix can
166 * be used to give the class name a prefix.
166 * be used to give the class name a prefix.
167 *
167 *
168 * The \a option flags can be used to tweak various parameters, such as
168 * The \a option flags can be used to tweak various parameters, such as
169 * showing static, original vs renamed name, underscores for space etc.
169 * showing static, original vs renamed name, underscores for space etc.
170 *
170 *
171 * The \a extra_arguments list is a list of extra arguments on the
171 * The \a extra_arguments list is a list of extra arguments on the
172 * form "bool static_call".
172 * form "bool static_call".
173 */
173 */
174
174
175 void ShellGenerator::writeFunctionSignature(QTextStream &s,
175 void ShellGenerator::writeFunctionSignature(QTextStream &s,
176 const AbstractMetaFunction *meta_function,
176 const AbstractMetaFunction *meta_function,
177 const AbstractMetaClass *implementor,
177 const AbstractMetaClass *implementor,
178 const QString &name_prefix,
178 const QString &name_prefix,
179 Option option,
179 Option option,
180 const QString &classname_prefix,
180 const QString &classname_prefix,
181 const QStringList &extra_arguments,
181 const QStringList &extra_arguments,
182 int numArguments)
182 int numArguments)
183 {
183 {
184 // ### remove the implementor
184 // ### remove the implementor
185 AbstractMetaType *function_type = meta_function->type();
185 AbstractMetaType *function_type = meta_function->type();
186
186
187
187
188 if ((option & SkipReturnType) == 0) {
188 if ((option & SkipReturnType) == 0) {
189 if (function_type) {
189 if (function_type) {
190 writeTypeInfo(s, function_type, option);
190 writeTypeInfo(s, function_type, option);
191 s << " ";
191 s << " ";
192 } else if (!meta_function->isConstructor()) {
192 } else if (!meta_function->isConstructor()) {
193 s << "void ";
193 s << "void ";
194 }
194 }
195 }
195 }
196
196
197 if (implementor) {
197 if (implementor) {
198 if (classname_prefix.isEmpty())
198 if (classname_prefix.isEmpty())
199 s << wrapperClassName(implementor) << "::";
199 s << wrapperClassName(implementor) << "::";
200 else
200 else
201 s << classname_prefix << implementor->name() << "::";
201 s << classname_prefix << implementor->name() << "::";
202 }
202 }
203
203
204
204
205 QString function_name;
205 QString function_name;
206 if (option & OriginalName)
206 if (option & OriginalName)
207 function_name = meta_function->originalName();
207 function_name = meta_function->originalName();
208 else
208 else
209 function_name = meta_function->name();
209 function_name = meta_function->name();
210
210
211 if (option & UnderscoreSpaces)
211 if (option & UnderscoreSpaces)
212 function_name = function_name.replace(' ', '_');
212 function_name = function_name.replace(' ', '_');
213
213
214 if (meta_function->isConstructor())
214 if (meta_function->isConstructor())
215 function_name = meta_function->ownerClass()->name();
215 function_name = meta_function->ownerClass()->name();
216
216
217 if (meta_function->isStatic() && (option & ShowStatic)) {
217 if (meta_function->isStatic() && (option & ShowStatic)) {
218 function_name = "static_" + meta_function->ownerClass()->name() + "_" + function_name;
218 function_name = "static_" + meta_function->ownerClass()->name() + "_" + function_name;
219 }
219 }
220
220
221 if (function_name.startsWith("operator")) {
221 if (function_name.startsWith("operator")) {
222 function_name = meta_function->name();
222 function_name = meta_function->name();
223 }
223 }
224
224
225 if (meta_function->attributes() & AbstractMetaAttributes::SetterFunction)
225 if (meta_function->attributes() & AbstractMetaAttributes::SetterFunction)
226 s << "setter_";
226 s << "py_set_";
227 else if (meta_function->attributes() & AbstractMetaAttributes::GetterFunction)
227 else if (meta_function->attributes() & AbstractMetaAttributes::GetterFunction)
228 s << "getter_";
228 s << "py_get_";
229
229
230 s << name_prefix << function_name;
230 s << name_prefix << function_name;
231
231
232 s << "(";
232 s << "(";
233
233
234 if ((option & FirstArgIsWrappedObject) && meta_function->ownerClass() && !meta_function->isConstructor() && !meta_function->isStatic()) {
234 if ((option & FirstArgIsWrappedObject) && meta_function->ownerClass() && !meta_function->isConstructor() && !meta_function->isStatic()) {
235 s << meta_function->ownerClass()->qualifiedCppName() << "* theWrappedObject";
235 s << meta_function->ownerClass()->qualifiedCppName() << "* theWrappedObject";
236 if (meta_function->arguments().size() != 0) {
236 if (meta_function->arguments().size() != 0) {
237 s << ", ";
237 s << ", ";
238 }
238 }
239 }
239 }
240
240
241 writeFunctionArguments(s, meta_function->ownerClass(), meta_function->arguments(), Option(option & Option(~ConvertReferenceToPtr)), numArguments);
241 writeFunctionArguments(s, meta_function->ownerClass(), meta_function->arguments(), Option(option & Option(~ConvertReferenceToPtr)), numArguments);
242
242
243 // The extra arguments...
243 // The extra arguments...
244 for (int i=0; i<extra_arguments.size(); ++i) {
244 for (int i=0; i<extra_arguments.size(); ++i) {
245 if (i > 0 || meta_function->arguments().size() != 0)
245 if (i > 0 || meta_function->arguments().size() != 0)
246 s << ", ";
246 s << ", ";
247 s << extra_arguments.at(i);
247 s << extra_arguments.at(i);
248 }
248 }
249
249
250 s << ")";
250 s << ")";
251 if (meta_function->isConstant())
251 if (meta_function->isConstant())
252 s << " const";
252 s << " const";
253 }
253 }
254
254
255 AbstractMetaFunctionList ShellGenerator::getFunctionsToWrap(const AbstractMetaClass* meta_class)
255 AbstractMetaFunctionList ShellGenerator::getFunctionsToWrap(const AbstractMetaClass* meta_class)
256 {
256 {
257 AbstractMetaFunctionList functions = meta_class->queryFunctions(
257 AbstractMetaFunctionList functions = meta_class->queryFunctions(
258 AbstractMetaClass::NormalFunctions | AbstractMetaClass::WasPublic
258 AbstractMetaClass::NormalFunctions | AbstractMetaClass::WasPublic
259 | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
259 | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
260 );
260 );
261 AbstractMetaFunctionList functions2 = meta_class->queryFunctions(
261 AbstractMetaFunctionList functions2 = meta_class->queryFunctions(
262 AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
262 AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
263 | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
263 | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
264 );
264 );
265 QSet<AbstractMetaFunction*> set1 = QSet<AbstractMetaFunction*>::fromList(functions);
265 QSet<AbstractMetaFunction*> set1 = QSet<AbstractMetaFunction*>::fromList(functions);
266 foreach(AbstractMetaFunction* func, functions2) {
266 foreach(AbstractMetaFunction* func, functions2) {
267 set1.insert(func);
267 set1.insert(func);
268 }
268 }
269
269
270 AbstractMetaFunctionList resultFunctions;
270 AbstractMetaFunctionList resultFunctions;
271
271
272 foreach(AbstractMetaFunction* func, set1.toList()) {
272 foreach(AbstractMetaFunction* func, set1.toList()) {
273 if (!func->isAbstract() && func->implementingClass()==meta_class) {
273 if (!func->isAbstract() && func->implementingClass()==meta_class) {
274 resultFunctions << func;
274 resultFunctions << func;
275 }
275 }
276 }
276 }
277 qStableSort(resultFunctions);
277 qStableSort(resultFunctions);
278 return resultFunctions;
278 return resultFunctions;
279 }
279 }
280
280
281 AbstractMetaFunctionList ShellGenerator::getVirtualFunctionsForShell(const AbstractMetaClass* meta_class)
281 AbstractMetaFunctionList ShellGenerator::getVirtualFunctionsForShell(const AbstractMetaClass* meta_class)
282 {
282 {
283 AbstractMetaFunctionList functions = meta_class->queryFunctions(
283 AbstractMetaFunctionList functions = meta_class->queryFunctions(
284 AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
284 AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
285 // | AbstractMetaClass::NotRemovedFromTargetLang
285 // | AbstractMetaClass::NotRemovedFromTargetLang
286 );
286 );
287 qStableSort(functions);
287 qStableSort(functions);
288 return functions;
288 return functions;
289 }
289 }
290
290
291 AbstractMetaFunctionList ShellGenerator::getProtectedFunctionsThatNeedPromotion(const AbstractMetaClass* meta_class)
291 AbstractMetaFunctionList ShellGenerator::getProtectedFunctionsThatNeedPromotion(const AbstractMetaClass* meta_class)
292 {
292 {
293 AbstractMetaFunctionList functions;
293 AbstractMetaFunctionList functions;
294 AbstractMetaFunctionList functions1 = getFunctionsToWrap(meta_class);
294 AbstractMetaFunctionList functions1 = getFunctionsToWrap(meta_class);
295 foreach(AbstractMetaFunction* func, functions1) {
295 foreach(AbstractMetaFunction* func, functions1) {
296 if (!func->isPublic() || func->isVirtual()) {
296 if (!func->isPublic() || func->isVirtual()) {
297 functions << func;
297 functions << func;
298 }
298 }
299 }
299 }
300 qStableSort(functions);
300 qStableSort(functions);
301 return functions;
301 return functions;
302 }
302 }
303
303
304 /*!
304 /*!
305 Writes the include defined by \a inc to \a stream.
305 Writes the include defined by \a inc to \a stream.
306 */
306 */
307 void ShellGenerator::writeInclude(QTextStream &stream, const Include &inc)
307 void ShellGenerator::writeInclude(QTextStream &stream, const Include &inc)
308 {
308 {
309 if (inc.name.isEmpty())
309 if (inc.name.isEmpty())
310 return;
310 return;
311 if (inc.type == Include::TargetLangImport)
311 if (inc.type == Include::TargetLangImport)
312 return;
312 return;
313 stream << "#include ";
313 stream << "#include ";
314 if (inc.type == Include::IncludePath)
314 if (inc.type == Include::IncludePath)
315 stream << "<";
315 stream << "<";
316 else
316 else
317 stream << "\"";
317 stream << "\"";
318 stream << inc.name;
318 stream << inc.name;
319 if (inc.type == Include::IncludePath)
319 if (inc.type == Include::IncludePath)
320 stream << ">";
320 stream << ">";
321 else
321 else
322 stream << "\"";
322 stream << "\"";
323 stream << endl;
323 stream << endl;
324 }
324 }
325
325
326 /*!
326 /*!
327 Returns true if the given function \a fun is operator>>() or
327 Returns true if the given function \a fun is operator>>() or
328 operator<<() that streams from/to a Q{Data,Text}Stream, false
328 operator<<() that streams from/to a Q{Data,Text}Stream, false
329 otherwise.
329 otherwise.
330 */
330 */
331 bool ShellGenerator::isSpecialStreamingOperator(const AbstractMetaFunction *fun)
331 bool ShellGenerator::isSpecialStreamingOperator(const AbstractMetaFunction *fun)
332 {
332 {
333 return ((fun->functionType() == AbstractMetaFunction::GlobalScopeFunction)
333 return ((fun->functionType() == AbstractMetaFunction::GlobalScopeFunction)
334 && (fun->arguments().size() == 1)
334 && (fun->arguments().size() == 1)
335 && (((fun->originalName() == "operator>>") && (fun->modifiedName() == "readFrom"))
335 && (((fun->originalName() == "operator>>") && (fun->modifiedName() == "readFrom"))
336 || ((fun->originalName() == "operator<<") && (fun->modifiedName() == "writeTo"))));
336 || ((fun->originalName() == "operator<<") && (fun->modifiedName() == "writeTo"))));
337 }
337 }
338
338
339 bool ShellGenerator::isBuiltIn(const QString& name) {
339 bool ShellGenerator::isBuiltIn(const QString& name) {
340
340
341 static QSet<QString> builtIn;
341 static QSet<QString> builtIn;
342 if (builtIn.isEmpty()) {
342 if (builtIn.isEmpty()) {
343 builtIn.insert("Qt");
343 builtIn.insert("Qt");
344 builtIn.insert("QFont");
344 builtIn.insert("QFont");
345 builtIn.insert("QPixmap");
345 builtIn.insert("QPixmap");
346 builtIn.insert("QBrush");
346 builtIn.insert("QBrush");
347 builtIn.insert("QBitArray");
347 builtIn.insert("QBitArray");
348 builtIn.insert("QPalette");
348 builtIn.insert("QPalette");
349 builtIn.insert("QPen");
349 builtIn.insert("QPen");
350 builtIn.insert("QIcon");
350 builtIn.insert("QIcon");
351 builtIn.insert("QImage");
351 builtIn.insert("QImage");
352 builtIn.insert("QPolygon");
352 builtIn.insert("QPolygon");
353 builtIn.insert("QRegion");
353 builtIn.insert("QRegion");
354 builtIn.insert("QBitmap");
354 builtIn.insert("QBitmap");
355 builtIn.insert("QCursor");
355 builtIn.insert("QCursor");
356 builtIn.insert("QColor");
356 builtIn.insert("QColor");
357 builtIn.insert("QSizePolicy");
357 builtIn.insert("QSizePolicy");
358 builtIn.insert("QKeySequence");
358 builtIn.insert("QKeySequence");
359 builtIn.insert("QTextLength");
359 builtIn.insert("QTextLength");
360 builtIn.insert("QTextFormat");
360 builtIn.insert("QTextFormat");
361 builtIn.insert("QMatrix");
361 builtIn.insert("QMatrix");
362 builtIn.insert("QDate");
362 builtIn.insert("QDate");
363 builtIn.insert("QTime");
363 builtIn.insert("QTime");
364 builtIn.insert("QDateTime");
364 builtIn.insert("QDateTime");
365 builtIn.insert("QUrl");
365 builtIn.insert("QUrl");
366 builtIn.insert("QLocale");
366 builtIn.insert("QLocale");
367 builtIn.insert("QRect");
367 builtIn.insert("QRect");
368 builtIn.insert("QRectF");
368 builtIn.insert("QRectF");
369 builtIn.insert("QSize");
369 builtIn.insert("QSize");
370 builtIn.insert("QSizeF");
370 builtIn.insert("QSizeF");
371 builtIn.insert("QLine");
371 builtIn.insert("QLine");
372 builtIn.insert("QLineF");
372 builtIn.insert("QLineF");
373 builtIn.insert("QPoint");
373 builtIn.insert("QPoint");
374 builtIn.insert("QPointF");
374 builtIn.insert("QPointF");
375 builtIn.insert("QRegExp");
375 builtIn.insert("QRegExp");
376 }
376 }
377 return builtIn.contains(name);
377 return builtIn.contains(name);
378 }
378 }
379
379
@@ -1,303 +1,306
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #include "shellheadergenerator.h"
42 #include "shellheadergenerator.h"
43 #include "fileout.h"
43 #include "fileout.h"
44
44
45 #include <QtCore/QDir>
45 #include <QtCore/QDir>
46
46
47 #include <qdebug.h>
47 #include <qdebug.h>
48
48
49 QString ShellHeaderGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
49 QString ShellHeaderGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
50 {
50 {
51 return QString("PythonQtWrapper_%1.h").arg(meta_class->name());
51 return QString("PythonQtWrapper_%1.h").arg(meta_class->name());
52 }
52 }
53
53
54
54
55 void ShellHeaderGenerator::writeFieldAccessors(QTextStream &s, const AbstractMetaField *field)
55 void ShellHeaderGenerator::writeFieldAccessors(QTextStream &s, const AbstractMetaField *field)
56 {
56 {
57 const AbstractMetaFunction *setter = field->setter();
57 const AbstractMetaFunction *setter = field->setter();
58 const AbstractMetaFunction *getter = field->getter();
58 const AbstractMetaFunction *getter = field->getter();
59
59
60 // Uuid data4 did not work
61 if (field->enclosingClass()->name()=="QUuid" && setter->name()=="data4") return;
62
60 if (!field->type()->isConstant()) {
63 if (!field->type()->isConstant()) {
61 writeFunctionSignature(s, setter, 0, QString(),
64 writeFunctionSignature(s, setter, 0, QString(),
62 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | ShowStatic | UnderscoreSpaces));
65 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | ShowStatic | UnderscoreSpaces));
63 s << "{ theWrappedObject->" << field->name() << " = " << setter->arguments()[0]->argumentName() << "; }\n";
66 s << "{ theWrappedObject->" << field->name() << " = " << setter->arguments()[0]->argumentName() << "; }\n";
64 }
67 }
65
68
66 writeFunctionSignature(s, getter, 0, QString(),
69 writeFunctionSignature(s, getter, 0, QString(),
67 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
70 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
68 s << "{ return theWrappedObject->" << field->name() << "; }\n";
71 s << "{ return theWrappedObject->" << field->name() << "; }\n";
69 }
72 }
70
73
71 void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
74 void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
72 {
75 {
73 QString builtIn = ShellGenerator::isBuiltIn(meta_class->name())?"_builtin":"";
76 QString builtIn = ShellGenerator::isBuiltIn(meta_class->name())?"_builtin":"";
74 QString pro_file_name = meta_class->package().replace(".", "_") + builtIn + "/" + meta_class->package().replace(".", "_") + builtIn + ".pri";
77 QString pro_file_name = meta_class->package().replace(".", "_") + builtIn + "/" + meta_class->package().replace(".", "_") + builtIn + ".pri";
75 priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
78 priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
76 setupGenerator->addClass(meta_class->package().replace(".", "_") + builtIn, meta_class);
79 setupGenerator->addClass(meta_class->package().replace(".", "_") + builtIn, meta_class);
77
80
78 QString include_block = "PYTHONQTWRAPPER_" + meta_class->name().toUpper() + "_H";
81 QString include_block = "PYTHONQTWRAPPER_" + meta_class->name().toUpper() + "_H";
79
82
80 s << "#ifndef " << include_block << endl
83 s << "#ifndef " << include_block << endl
81 << "#define " << include_block << endl << endl;
84 << "#define " << include_block << endl << endl;
82
85
83 Include inc = meta_class->typeEntry()->include();
86 Include inc = meta_class->typeEntry()->include();
84 ShellGenerator::writeInclude(s, inc);
87 ShellGenerator::writeInclude(s, inc);
85
88
86 s << "#include <QObject>" << endl << endl;
89 s << "#include <QObject>" << endl << endl;
87 s << "#include <PythonQt.h>" << endl << endl;
90 s << "#include <PythonQt.h>" << endl << endl;
88
91
89 IncludeList list = meta_class->typeEntry()->extraIncludes();
92 IncludeList list = meta_class->typeEntry()->extraIncludes();
90 qSort(list.begin(), list.end());
93 qSort(list.begin(), list.end());
91 foreach (const Include &inc, list) {
94 foreach (const Include &inc, list) {
92 ShellGenerator::writeInclude(s, inc);
95 ShellGenerator::writeInclude(s, inc);
93 }
96 }
94 s << endl;
97 s << endl;
95
98
96 AbstractMetaFunctionList ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
99 AbstractMetaFunctionList ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
97 | AbstractMetaClass::WasVisible
100 | AbstractMetaClass::WasVisible
98 | AbstractMetaClass::NotRemovedFromTargetLang);
101 | AbstractMetaClass::NotRemovedFromTargetLang);
99
102
100 // Shell-------------------------------------------------------------------
103 // Shell-------------------------------------------------------------------
101 if (meta_class->generateShellClass()) {
104 if (meta_class->generateShellClass()) {
102
105
103 AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);
106 AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);
104
107
105 s << "class " << shellClassName(meta_class)
108 s << "class " << shellClassName(meta_class)
106 << " : public " << meta_class->qualifiedCppName() << endl << "{" << endl;
109 << " : public " << meta_class->qualifiedCppName() << endl << "{" << endl;
107 s << "public:" << endl;
110 s << "public:" << endl;
108 foreach(AbstractMetaFunction* fun, ctors) {
111 foreach(AbstractMetaFunction* fun, ctors) {
109 s << " ";
112 s << " ";
110 writeFunctionSignature(s, fun, 0,"PythonQtShell_",
113 writeFunctionSignature(s, fun, 0,"PythonQtShell_",
111 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
114 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
112 s << ":" << meta_class->qualifiedCppName() << "(";
115 s << ":" << meta_class->qualifiedCppName() << "(";
113 QString scriptFunctionName = fun->originalName();
116 QString scriptFunctionName = fun->originalName();
114 AbstractMetaArgumentList args = fun->arguments();
117 AbstractMetaArgumentList args = fun->arguments();
115 for (int i = 0; i < args.size(); ++i) {
118 for (int i = 0; i < args.size(); ++i) {
116 if (i > 0)
119 if (i > 0)
117 s << ", ";
120 s << ", ";
118 s << args.at(i)->argumentName();
121 s << args.at(i)->argumentName();
119 }
122 }
120 s << "),_wrapper(NULL) {};" << endl;
123 s << "),_wrapper(NULL) {};" << endl;
121 }
124 }
122 s << endl;
125 s << endl;
123
126
124 foreach(AbstractMetaFunction* fun, virtualsForShell) {
127 foreach(AbstractMetaFunction* fun, virtualsForShell) {
125 s << "virtual ";
128 s << "virtual ";
126 writeFunctionSignature(s, fun, 0, QString(),
129 writeFunctionSignature(s, fun, 0, QString(),
127 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
130 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
128 s << ";" << endl;
131 s << ";" << endl;
129 }
132 }
130 s << endl;
133 s << endl;
131 s << " PythonQtInstanceWrapper* _wrapper; " << endl;
134 s << " PythonQtInstanceWrapper* _wrapper; " << endl;
132
135
133 s << "};" << endl << endl;
136 s << "};" << endl << endl;
134 }
137 }
135
138
136 // Promoter-------------------------------------------------------------------
139 // Promoter-------------------------------------------------------------------
137 AbstractMetaFunctionList promoteFunctions = getProtectedFunctionsThatNeedPromotion(meta_class);
140 AbstractMetaFunctionList promoteFunctions = getProtectedFunctionsThatNeedPromotion(meta_class);
138 if (!promoteFunctions.isEmpty()) {
141 if (!promoteFunctions.isEmpty()) {
139 s << "class " << promoterClassName(meta_class)
142 s << "class " << promoterClassName(meta_class)
140 << " : public " << meta_class->qualifiedCppName() << endl << "{ public:" << endl;
143 << " : public " << meta_class->qualifiedCppName() << endl << "{ public:" << endl;
141
144
142 foreach(AbstractMetaFunction* fun, promoteFunctions) {
145 foreach(AbstractMetaFunction* fun, promoteFunctions) {
143 s << "inline ";
146 s << "inline ";
144 writeFunctionSignature(s, fun, 0, "promoted_",
147 writeFunctionSignature(s, fun, 0, "promoted_",
145 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
148 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
146 s << " { ";
149 s << " { ";
147 QString scriptFunctionName = fun->originalName();
150 QString scriptFunctionName = fun->originalName();
148 AbstractMetaArgumentList args = fun->arguments();
151 AbstractMetaArgumentList args = fun->arguments();
149 if (fun->type())
152 if (fun->type())
150 s << "return ";
153 s << "return ";
151 s << meta_class->qualifiedCppName() << "::";
154 s << meta_class->qualifiedCppName() << "::";
152 s << fun->originalName() << "(";
155 s << fun->originalName() << "(";
153 for (int i = 0; i < args.size(); ++i) {
156 for (int i = 0; i < args.size(); ++i) {
154 if (i > 0)
157 if (i > 0)
155 s << ", ";
158 s << ", ";
156 s << args.at(i)->argumentName();
159 s << args.at(i)->argumentName();
157 }
160 }
158 s << "); }" << endl;
161 s << "); }" << endl;
159 }
162 }
160
163
161 s << "};" << endl << endl;
164 s << "};" << endl << endl;
162 }
165 }
163
166
164 // Wrapper-------------------------------------------------------------------
167 // Wrapper-------------------------------------------------------------------
165
168
166 s << "class " << wrapperClassName(meta_class)
169 s << "class " << wrapperClassName(meta_class)
167 << " : public QObject" << endl
170 << " : public QObject" << endl
168 << "{ Q_OBJECT" << endl;
171 << "{ Q_OBJECT" << endl;
169
172
170 s << "public:" << endl;
173 s << "public:" << endl;
171
174
172 AbstractMetaEnumList enums1 = meta_class->enums();
175 AbstractMetaEnumList enums1 = meta_class->enums();
173 AbstractMetaEnumList enums;
176 AbstractMetaEnumList enums;
174 QList<FlagsTypeEntry*> flags;
177 QList<FlagsTypeEntry*> flags;
175 foreach(AbstractMetaEnum* enum1, enums1) {
178 foreach(AbstractMetaEnum* enum1, enums1) {
176 // catch gadgets and enums that are not exported on QObjects...
179 // catch gadgets and enums that are not exported on QObjects...
177 if (enum1->wasPublic() && (!meta_class->isQObject() || !enum1->hasQEnumsDeclaration())) {
180 if (enum1->wasPublic() && (!meta_class->isQObject() || !enum1->hasQEnumsDeclaration())) {
178 enums << enum1;
181 enums << enum1;
179 if (enum1->typeEntry()->flags()) {
182 if (enum1->typeEntry()->flags()) {
180 flags << enum1->typeEntry()->flags();
183 flags << enum1->typeEntry()->flags();
181 }
184 }
182 }
185 }
183 }
186 }
184 if (enums.count()) {
187 if (enums.count()) {
185 s << "Q_ENUMS(";
188 s << "Q_ENUMS(";
186 foreach(AbstractMetaEnum* enum1, enums) {
189 foreach(AbstractMetaEnum* enum1, enums) {
187 s << enum1->name() << " ";
190 s << enum1->name() << " ";
188 }
191 }
189 s << ")" << endl;
192 s << ")" << endl;
190
193
191 if (flags.count()) {
194 if (flags.count()) {
192 s << "Q_FLAGS(";
195 s << "Q_FLAGS(";
193 foreach(FlagsTypeEntry* flag1, flags) {
196 foreach(FlagsTypeEntry* flag1, flags) {
194 QString origName = flag1->originalName();
197 QString origName = flag1->originalName();
195 int idx = origName.lastIndexOf("::");
198 int idx = origName.lastIndexOf("::");
196 if (idx!= -1) {
199 if (idx!= -1) {
197 origName = origName.mid(idx+2);
200 origName = origName.mid(idx+2);
198 }
201 }
199 s << origName << " ";
202 s << origName << " ";
200 }
203 }
201 s << ")" << endl;
204 s << ")" << endl;
202 }
205 }
203
206
204 foreach(AbstractMetaEnum* enum1, enums) {
207 foreach(AbstractMetaEnum* enum1, enums) {
205 s << "enum " << enum1->name() << "{" << endl;
208 s << "enum " << enum1->name() << "{" << endl;
206 bool first = true;
209 bool first = true;
207 foreach(AbstractMetaEnumValue* value, enum1->values()) {
210 foreach(AbstractMetaEnumValue* value, enum1->values()) {
208 if (first) { first = false; }
211 if (first) { first = false; }
209 else { s << ", "; }
212 else { s << ", "; }
210 s << " " << value->name() << " = " << meta_class->qualifiedCppName() << "::" << value->name();
213 s << " " << value->name() << " = " << meta_class->qualifiedCppName() << "::" << value->name();
211 }
214 }
212 s << "};" << endl;
215 s << "};" << endl;
213 }
216 }
214 if (flags.count()) {
217 if (flags.count()) {
215 foreach(AbstractMetaEnum* enum1, enums) {
218 foreach(AbstractMetaEnum* enum1, enums) {
216 if (enum1->typeEntry()->flags()) {
219 if (enum1->typeEntry()->flags()) {
217 QString origName = enum1->typeEntry()->flags()->originalName();
220 QString origName = enum1->typeEntry()->flags()->originalName();
218 int idx = origName.lastIndexOf("::");
221 int idx = origName.lastIndexOf("::");
219 if (idx!= -1) {
222 if (idx!= -1) {
220 origName = origName.mid(idx+2);
223 origName = origName.mid(idx+2);
221 }
224 }
222 s << "Q_DECLARE_FLAGS("<< origName << ", " << enum1->name() <<")"<<endl;
225 s << "Q_DECLARE_FLAGS("<< origName << ", " << enum1->name() <<")"<<endl;
223 }
226 }
224 }
227 }
225 }
228 }
226 }
229 }
227 s << "public slots:" << endl;
230 s << "public slots:" << endl;
228 if (meta_class->generateShellClass() || !meta_class->isAbstract()) {
231 if (meta_class->generateShellClass() || !meta_class->isAbstract()) {
229
232
230 bool copyConstructorSeen = false;
233 bool copyConstructorSeen = false;
231 bool defaultConstructorSeen = false;
234 bool defaultConstructorSeen = false;
232 foreach (const AbstractMetaFunction *fun, ctors) {
235 foreach (const AbstractMetaFunction *fun, ctors) {
233 if (!fun->isPublic() || fun->isAbstract()) { continue; }
236 if (!fun->isPublic() || fun->isAbstract()) { continue; }
234 s << meta_class->qualifiedCppName() << "* ";
237 s << meta_class->qualifiedCppName() << "* ";
235 writeFunctionSignature(s, fun, 0, "new_",
238 writeFunctionSignature(s, fun, 0, "new_",
236 Option(IncludeDefaultExpression | OriginalName | ShowStatic));
239 Option(IncludeDefaultExpression | OriginalName | ShowStatic));
237 s << ";" << endl;
240 s << ";" << endl;
238 if (fun->arguments().size()==1 && meta_class->qualifiedCppName() == fun->arguments().at(0)->type()->typeEntry()->qualifiedCppName()) {
241 if (fun->arguments().size()==1 && meta_class->qualifiedCppName() == fun->arguments().at(0)->type()->typeEntry()->qualifiedCppName()) {
239 copyConstructorSeen = true;
242 copyConstructorSeen = true;
240 }
243 }
241 if (fun->arguments().size()==0) {
244 if (fun->arguments().size()==0) {
242 defaultConstructorSeen = true;
245 defaultConstructorSeen = true;
243 }
246 }
244 }
247 }
245
248
246 if (meta_class->typeEntry()->isValue()
249 if (meta_class->typeEntry()->isValue()
247 && !copyConstructorSeen && defaultConstructorSeen) {
250 && !copyConstructorSeen && defaultConstructorSeen) {
248 QString className = meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName();
251 QString className = meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName();
249 s << meta_class->qualifiedCppName() << "* new_" << meta_class->name() << "(const " << meta_class->qualifiedCppName() << "& other) {" << endl;
252 s << meta_class->qualifiedCppName() << "* new_" << meta_class->name() << "(const " << meta_class->qualifiedCppName() << "& other) {" << endl;
250 s << className << "* a = new " << className << "();" << endl;
253 s << className << "* a = new " << className << "();" << endl;
251 s << "*((" << meta_class->qualifiedCppName() << "*)a) = other;" << endl;
254 s << "*((" << meta_class->qualifiedCppName() << "*)a) = other;" << endl;
252 s << "return a; }" << endl;
255 s << "return a; }" << endl;
253 }
256 }
254 }
257 }
255 if (meta_class->hasPublicDestructor() && !meta_class->isNamespace()) {
258 if (meta_class->hasPublicDestructor() && !meta_class->isNamespace()) {
256 s << "void delete_" << meta_class->name() << "(" << meta_class->qualifiedCppName() << "* obj) { delete obj; } ";
259 s << "void delete_" << meta_class->name() << "(" << meta_class->qualifiedCppName() << "* obj) { delete obj; } ";
257 s << endl;
260 s << endl;
258 }
261 }
259 if (meta_class->name()=="QTreeWidgetItem") {
262 if (meta_class->name()=="QTreeWidgetItem") {
260 s << "bool hasOwner(QTreeWidgetItem* theWrappedObject) { return theWrappedObject->treeWidget()!=NULL || theWrappedObject->parent()!=NULL; }" << endl;
263 s << "bool py_hasOwner(QTreeWidgetItem* theWrappedObject) { return theWrappedObject->treeWidget()!=NULL || theWrappedObject->parent()!=NULL; }" << endl;
261 } else if (meta_class->name()=="QGraphicsItem") {
264 } else if (meta_class->name()=="QGraphicsItem") {
262 s << "bool hasOwner(QGraphicsItem* theWrappedObject) { return theWrappedObject->scene()!=NULL || theWrappedObject->parentItem()!=NULL; }" << endl;
265 s << "bool py_hasOwner(QGraphicsItem* theWrappedObject) { return theWrappedObject->scene()!=NULL || theWrappedObject->parentItem()!=NULL; }" << endl;
263 }
266 }
264
267
265 AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);
268 AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);
266
269
267 foreach (const AbstractMetaFunction *function, functions) {
270 foreach (const AbstractMetaFunction *function, functions) {
268 if (!function->isSlot()) {
271 if (!function->isSlot()) {
269 s << " ";
272 s << " ";
270 writeFunctionSignature(s, function, 0, QString(),
273 writeFunctionSignature(s, function, 0, QString(),
271 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
274 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
272 s << ";" << endl;
275 s << ";" << endl;
273 }
276 }
274 }
277 }
275 if (!meta_class->hasDefaultToStringFunction() && meta_class->hasToStringCapability()) {
278 if (meta_class->hasDefaultToStringFunction() || meta_class->hasToStringCapability()) {
276 s << " QString toString(" << meta_class->qualifiedCppName() << "*);" << endl;
279 s << " QString py_toString(" << meta_class->qualifiedCppName() << "*);" << endl;
277 }
280 }
278
281
279 // Field accessors
282 // Field accessors
280 foreach (const AbstractMetaField *field, meta_class->fields()) {
283 foreach (const AbstractMetaField *field, meta_class->fields()) {
281 if (field->isPublic()) {
284 if (field->isPublic()) {
282 writeFieldAccessors(s, field);
285 writeFieldAccessors(s, field);
283 }
286 }
284 }
287 }
285
288
286 // writeInjectedCode(s, meta_class);
289 // writeInjectedCode(s, meta_class);
287
290
288 // s << endl << " QScriptValue __qtscript_self;" << endl;
291 // s << endl << " QScriptValue __qtscript_self;" << endl;
289
292
290 s << "};" << endl << endl
293 s << "};" << endl << endl
291 << "#endif // " << include_block << endl;
294 << "#endif // " << include_block << endl;
292
295
293 }
296 }
294
297
295 void ShellHeaderGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
298 void ShellHeaderGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
296 {
299 {
297 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
300 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
298 foreach (const CodeSnip &cs, code_snips) {
301 foreach (const CodeSnip &cs, code_snips) {
299 if (cs.language == TypeSystem::ShellDeclaration) {
302 if (cs.language == TypeSystem::ShellDeclaration) {
300 s << cs.code() << endl;
303 s << cs.code() << endl;
301 }
304 }
302 }
305 }
303 }
306 }
@@ -1,309 +1,311
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #include "shellimplgenerator.h"
42 #include "shellimplgenerator.h"
43 #include "reporthandler.h"
43 #include "reporthandler.h"
44 #include "fileout.h"
44 #include "fileout.h"
45 #include <iostream>
45 #include <iostream>
46
46
47 extern void declareFunctionMetaTypes(QTextStream &stream,
47 extern void declareFunctionMetaTypes(QTextStream &stream,
48 const AbstractMetaFunctionList &functions,
48 const AbstractMetaFunctionList &functions,
49 QSet<QString> &registeredTypeNames);
49 QSet<QString> &registeredTypeNames);
50
50
51 QString ShellImplGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
51 QString ShellImplGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
52 {
52 {
53 return QString("PythonQtWrapper_%1.cpp").arg(meta_class->name());
53 return QString("PythonQtWrapper_%1.cpp").arg(meta_class->name());
54 }
54 }
55
55
56 static bool include_less_than(const Include &a, const Include &b)
56 static bool include_less_than(const Include &a, const Include &b)
57 {
57 {
58 return a.name < b.name;
58 return a.name < b.name;
59 }
59 }
60
60
61 static void writeHelperCode(QTextStream &s, const AbstractMetaClass *)
61 static void writeHelperCode(QTextStream &s, const AbstractMetaClass *)
62 {
62 {
63 }
63 }
64
64
65
65
66
66
67 void ShellImplGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
67 void ShellImplGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
68 {
68 {
69 QString builtIn = ShellGenerator::isBuiltIn(meta_class->name())?"_builtin":"";
69 QString builtIn = ShellGenerator::isBuiltIn(meta_class->name())?"_builtin":"";
70 QString pro_file_name = meta_class->package().replace(".", "_") + builtIn + "/" + meta_class->package().replace(".", "_") + builtIn + ".pri";
70 QString pro_file_name = meta_class->package().replace(".", "_") + builtIn + "/" + meta_class->package().replace(".", "_") + builtIn + ".pri";
71 priGenerator->addSource(pro_file_name, fileNameForClass(meta_class));
71 priGenerator->addSource(pro_file_name, fileNameForClass(meta_class));
72
72
73 s << "#include \"PythonQtWrapper_" << meta_class->name() << ".h\"" << endl << endl;
73 s << "#include \"PythonQtWrapper_" << meta_class->name() << ".h\"" << endl << endl;
74
74
75 s << "#include <PythonQtSignalReceiver.h>" << endl;
75 s << "#include <PythonQtSignalReceiver.h>" << endl;
76 s << "#include <PythonQtMethodInfo.h>" << endl;
76 s << "#include <PythonQtMethodInfo.h>" << endl;
77 s << "#include <PythonQtConversion.h>" << endl;
77 s << "#include <PythonQtConversion.h>" << endl;
78
78
79 //if (!meta_class->generateShellClass())
79 //if (!meta_class->generateShellClass())
80 // return;
80 // return;
81
81
82 IncludeList list = meta_class->typeEntry()->extraIncludes();
82 IncludeList list = meta_class->typeEntry()->extraIncludes();
83 qSort(list.begin(), list.end());
83 qSort(list.begin(), list.end());
84 foreach (const Include &inc, list) {
84 foreach (const Include &inc, list) {
85 ShellGenerator::writeInclude(s, inc);
85 ShellGenerator::writeInclude(s, inc);
86 }
86 }
87 s << endl;
87 s << endl;
88
88
89 writeHelperCode(s, meta_class);
89 writeHelperCode(s, meta_class);
90
90
91 // find constructors
91 // find constructors
92 AbstractMetaFunctionList ctors;
92 AbstractMetaFunctionList ctors;
93 ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
93 ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
94 | AbstractMetaClass::WasVisible
94 | AbstractMetaClass::WasVisible
95 | AbstractMetaClass::NotRemovedFromTargetLang);
95 | AbstractMetaClass::NotRemovedFromTargetLang);
96 // find member functions
96 // find member functions
97 AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);
97 AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);
98
98
99 // write metatype declarations
99 // write metatype declarations
100 {
100 {
101 // QSet<QString> registeredTypeNames = m_qmetatype_declared_typenames;
101 // QSet<QString> registeredTypeNames = m_qmetatype_declared_typenames;
102 // declareFunctionMetaTypes(s, functions, registeredTypeNames);
102 // declareFunctionMetaTypes(s, functions, registeredTypeNames);
103 // s << endl;
103 // s << endl;
104 }
104 }
105
105
106 if (meta_class->generateShellClass()) {
106 if (meta_class->generateShellClass()) {
107 AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);
107 AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);
108 foreach (const AbstractMetaFunction *fun, virtualsForShell) {
108 foreach (const AbstractMetaFunction *fun, virtualsForShell) {
109 bool hasReturnValue = (fun->type());
109 bool hasReturnValue = (fun->type());
110 writeFunctionSignature(s, fun, meta_class, QString(),
110 writeFunctionSignature(s, fun, meta_class, QString(),
111 Option(OriginalName | ShowStatic | UnderscoreSpaces),
111 Option(OriginalName | ShowStatic | UnderscoreSpaces),
112 "PythonQtShell_");
112 "PythonQtShell_");
113 s << endl << "{" << endl;
113 s << endl << "{" << endl;
114
114
115 Option typeOptions = Option(OriginalName | UnderscoreSpaces | SkipName);
115 Option typeOptions = Option(OriginalName | UnderscoreSpaces | SkipName);
116 AbstractMetaArgumentList args = fun->arguments();
116 AbstractMetaArgumentList args = fun->arguments();
117
117
118 s << "if (_wrapper) {" << endl;
118 s << "if (_wrapper) {" << endl;
119 s << " PyObject* obj = PyObject_GetAttrString((PyObject*)_wrapper, \"" << fun->name() << "\");" << endl;
119 s << " PyObject* obj = PyObject_GetAttrString((PyObject*)_wrapper, \"" << fun->name() << "\");" << endl;
120 s << " PyErr_Clear();" << endl;
120 s << " PyErr_Clear();" << endl;
121 s << " if (obj && !PythonQtSlotFunction_Check(obj)) {" << endl;
121 s << " if (obj && !PythonQtSlotFunction_Check(obj)) {" << endl;
122 s << " static const char* argumentList[] ={\"";
122 s << " static const char* argumentList[] ={\"";
123 if (hasReturnValue) {
123 if (hasReturnValue) {
124 // write the arguments, return type first
124 // write the arguments, return type first
125 writeTypeInfo(s, fun->type(), typeOptions);
125 writeTypeInfo(s, fun->type(), typeOptions);
126 }
126 }
127 s << "\"";
127 s << "\"";
128 for (int i = 0; i < args.size(); ++i) {
128 for (int i = 0; i < args.size(); ++i) {
129 s << " , \"";
129 s << " , \"";
130 writeTypeInfo(s, args.at(i)->type(), typeOptions);
130 writeTypeInfo(s, args.at(i)->type(), typeOptions);
131 s << "\"";
131 s << "\"";
132 }
132 }
133 s << "};" << endl;
133 s << "};" << endl;
134 s << " static const PythonQtMethodInfo* methodInfo = PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(" << QString::number(args.size()+1) << ", argumentList);" << endl;
134 s << " static const PythonQtMethodInfo* methodInfo = PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(" << QString::number(args.size()+1) << ", argumentList);" << endl;
135
135
136 if (hasReturnValue) {
136 if (hasReturnValue) {
137 s << " ";
137 s << " ";
138 writeTypeInfo(s, fun->type(), typeOptions);
138 writeTypeInfo(s, fun->type(), typeOptions);
139 s << " returnValue;" << endl;
139 s << " returnValue;" << endl;
140 // TODO: POD init to default is missing...
140 // TODO: POD init to default is missing...
141 }
141 }
142 s << " void* args[" << QString::number(args.size()+1) << "] = {NULL";
142 s << " void* args[" << QString::number(args.size()+1) << "] = {NULL";
143 for (int i = 0; i < args.size(); ++i) {
143 for (int i = 0; i < args.size(); ++i) {
144 s << ", (void*)&" << args.at(i)->argumentName();
144 s << ", (void*)&" << args.at(i)->argumentName();
145 }
145 }
146 s << "};" << endl;
146 s << "};" << endl;
147
147
148 s << " PyObject* result = PythonQtSignalTarget::call(obj, methodInfo, args, true);" << endl;
148 s << " PyObject* result = PythonQtSignalTarget::call(obj, methodInfo, args, true);" << endl;
149 if (hasReturnValue) {
149 if (hasReturnValue) {
150 s << " if (result) {" << endl;
150 s << " if (result) {" << endl;
151 s << " args[0] = PythonQtConv::ConvertPythonToQt(methodInfo->parameters().at(0), result, false, NULL, &returnValue);" << endl;
151 s << " args[0] = PythonQtConv::ConvertPythonToQt(methodInfo->parameters().at(0), result, false, NULL, &returnValue);" << endl;
152 s << " if (args[0]!=&returnValue) {" << endl;
152 s << " if (args[0]!=&returnValue) {" << endl;
153 s << " if (args[0]==NULL) {" << endl;
153 s << " if (args[0]==NULL) {" << endl;
154 s << " PythonQt::priv()->handleVirtualOverloadReturnError(\"" << fun->name() << "\", methodInfo, result);" << endl;
154 s << " PythonQt::priv()->handleVirtualOverloadReturnError(\"" << fun->name() << "\", methodInfo, result);" << endl;
155 s << " } else {" << endl;
155 s << " } else {" << endl;
156 s << " returnValue = *((";
156 s << " returnValue = *((";
157 writeTypeInfo(s, fun->type(), typeOptions);
157 writeTypeInfo(s, fun->type(), typeOptions);
158 s << "*)args[0]);" << endl;
158 s << "*)args[0]);" << endl;
159 s << " }" << endl;
159 s << " }" << endl;
160 s << " }" << endl;
160 s << " }" << endl;
161 s << " }" << endl;
161 s << " }" << endl;
162 }
162 }
163 s << " if (result) { Py_DECREF(result); } " << endl;
163 s << " if (result) { Py_DECREF(result); } " << endl;
164 s << " Py_DECREF(obj);" << endl;
164 s << " Py_DECREF(obj);" << endl;
165 if (hasReturnValue) {
165 if (hasReturnValue) {
166 s << " return returnValue;" << endl;
166 s << " return returnValue;" << endl;
167 } else {
167 } else {
168 s << " return;" << endl;
168 s << " return;" << endl;
169 }
169 }
170 s << " }" << endl;
170 s << " }" << endl;
171 s << "}" << endl;
171 s << "}" << endl;
172
172
173 s << " ";
173 s << " ";
174 if (fun->isAbstract()) {
174 if (fun->isAbstract()) {
175 if (fun->type()) {
175 if (fun->type()) {
176 // return empty default object
176 // return empty default object
177 writeTypeInfo(s, fun->type(), typeOptions);
177 writeTypeInfo(s, fun->type(), typeOptions);
178 s << " result;" << endl;
178 s << " result;" << endl;
179 s << "return result";
179 s << "return result";
180 s << ";";
180 s << ";";
181 }
181 }
182 } else {
182 } else {
183 if (fun->type()) {
183 if (fun->type()) {
184 s << "return ";
184 s << "return ";
185 }
185 }
186 s << meta_class->qualifiedCppName() << "::";
186 s << meta_class->qualifiedCppName() << "::";
187 s << fun->originalName() << "(";
187 s << fun->originalName() << "(";
188 for (int i = 0; i < args.size(); ++i) {
188 for (int i = 0; i < args.size(); ++i) {
189 if (i > 0)
189 if (i > 0)
190 s << ", ";
190 s << ", ";
191 s << args.at(i)->argumentName();
191 s << args.at(i)->argumentName();
192 }
192 }
193 s << ");";
193 s << ");";
194 }
194 }
195 s << endl << "}" << endl;
195 s << endl << "}" << endl;
196 }
196 }
197 }
197 }
198
198
199 if (meta_class->generateShellClass() || !meta_class->isAbstract()) {
199 if (meta_class->generateShellClass() || !meta_class->isAbstract()) {
200
200
201 // write constructors
201 // write constructors
202 foreach (const AbstractMetaFunction *ctor, ctors) {
202 foreach (const AbstractMetaFunction *ctor, ctors) {
203 if (!ctor->isPublic() || ctor->isAbstract()) { continue; }
203 if (!ctor->isPublic() || ctor->isAbstract()) { continue; }
204
204
205 s << meta_class->qualifiedCppName() << "* ";
205 s << meta_class->qualifiedCppName() << "* ";
206 s << "PythonQtWrapper_" << meta_class->name() << "::";
206 s << "PythonQtWrapper_" << meta_class->name() << "::";
207 writeFunctionSignature(s, ctor, 0, "new_", Option(OriginalName | ShowStatic));
207 writeFunctionSignature(s, ctor, 0, "new_", Option(OriginalName | ShowStatic));
208 s << endl;
208 s << endl;
209 s << "{ " << endl;
209 s << "{ " << endl;
210 s << "return new " << (meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName()) << "(";
210 s << "return new " << (meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName()) << "(";
211 AbstractMetaArgumentList args = ctor->arguments();
211 AbstractMetaArgumentList args = ctor->arguments();
212 for (int i = 0; i < args.size(); ++i) {
212 for (int i = 0; i < args.size(); ++i) {
213 if (i > 0)
213 if (i > 0)
214 s << ", ";
214 s << ", ";
215 s << args.at(i)->argumentName();
215 s << args.at(i)->argumentName();
216 }
216 }
217 s << ");" << " }" << endl << endl;
217 s << ");" << " }" << endl << endl;
218 }
218 }
219 }
219 }
220
220
221 QString wrappedObject = " (*theWrappedObject)";
221 QString wrappedObject = " (*theWrappedObject)";
222
222
223 // write member functions
223 // write member functions
224 for (int i = 0; i < functions.size(); ++i) {
224 for (int i = 0; i < functions.size(); ++i) {
225 AbstractMetaFunction *fun = functions.at(i);
225 AbstractMetaFunction *fun = functions.at(i);
226 if (fun->isSlot()) continue;
226 if (fun->isSlot()) continue;
227
227
228 writeFunctionSignature(s, fun, meta_class, QString(),
228 writeFunctionSignature(s, fun, meta_class, QString(),
229 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject | OriginalName | ShowStatic | UnderscoreSpaces),
229 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject | OriginalName | ShowStatic | UnderscoreSpaces),
230 "PythonQtWrapper_");
230 "PythonQtWrapper_");
231 s << endl << "{" << endl;
231 s << endl << "{" << endl;
232 s << " ";
232 s << " ";
233 if (ShellGenerator::isSpecialStreamingOperator(fun)) {
233 if (ShellGenerator::isSpecialStreamingOperator(fun)) {
234 s << fun->arguments().at(0)->argumentName();
234 s << fun->arguments().at(0)->argumentName();
235 if (fun->originalName().startsWith("operator>>")) {
235 if (fun->originalName().startsWith("operator>>")) {
236 s << " >> ";
236 s << " >> ";
237 } else {
237 } else {
238 s << " << ";
238 s << " << ";
239 }
239 }
240 s << wrappedObject;
240 s << wrappedObject;
241 } else {
241 } else {
242 QString scriptFunctionName = fun->originalName();
242 QString scriptFunctionName = fun->originalName();
243 AbstractMetaArgumentList args = fun->arguments();
243 AbstractMetaArgumentList args = fun->arguments();
244 // call the C++ implementation
244 // call the C++ implementation
245 if (fun->type()) {
245 if (fun->type()) {
246 s << "return ";
246 s << "return ";
247 // call the C++ implementation
247 // call the C++ implementation
248 if (fun->type()->isReference()) {
248 if (fun->type()->isReference()) {
249 s << "&";
249 s << "&";
250 }
250 }
251 }
251 }
252 s << "(";
252 s << "(";
253 if (scriptFunctionName.startsWith("operator>>")) {
253 if (scriptFunctionName.startsWith("operator>>")) {
254 s << wrappedObject << " >>" << args.at(0)->argumentName();
254 s << wrappedObject << " >>" << args.at(0)->argumentName();
255 } else if (scriptFunctionName.startsWith("operator<<")) {
255 } else if (scriptFunctionName.startsWith("operator<<")) {
256 s << wrappedObject << " <<" << args.at(0)->argumentName();
256 s << wrappedObject << " <<" << args.at(0)->argumentName();
257 } else if (scriptFunctionName.startsWith("operator[]")) {
257 } else if (scriptFunctionName.startsWith("operator[]")) {
258 s << wrappedObject << "[" << args.at(0)->argumentName() << "]";
258 s << wrappedObject << "[" << args.at(0)->argumentName() << "]";
259 } else if (scriptFunctionName.startsWith("operator") && args.size()==1) {
259 } else if (scriptFunctionName.startsWith("operator") && args.size()==1) {
260 QString op = scriptFunctionName.mid(8);
260 QString op = scriptFunctionName.mid(8);
261 s << wrappedObject << op << " " << args.at(0)->argumentName();
261 s << wrappedObject << op << " " << args.at(0)->argumentName();
262 } else {
262 } else {
263 if (fun->isStatic()) {
263 if (fun->isStatic()) {
264 s << meta_class->qualifiedCppName() << "::";
264 s << meta_class->qualifiedCppName() << "::";
265 } else {
265 } else {
266 if (!fun->isPublic() || fun->isVirtual()) {
266 if (!fun->isPublic() || fun->isVirtual()) {
267 s << " ((" << promoterClassName(meta_class) << "*)theWrappedObject)->promoted_";
267 s << " ((" << promoterClassName(meta_class) << "*)theWrappedObject)->promoted_";
268 } else {
268 } else {
269 s << " theWrappedObject->";
269 s << " theWrappedObject->";
270 }
270 }
271 }
271 }
272 s << fun->originalName() << "(";
272 s << fun->originalName() << "(";
273 for (int i = 0; i < args.size(); ++i) {
273 for (int i = 0; i < args.size(); ++i) {
274 if (i > 0)
274 if (i > 0)
275 s << ", ";
275 s << ", ";
276 s << args.at(i)->argumentName();
276 s << args.at(i)->argumentName();
277 }
277 }
278 s << ")";
278 s << ")";
279 }
279 }
280 s << ")";
280 s << ")";
281 }
281 }
282 s << ";" << endl;
282 s << ";" << endl;
283
283
284 s << "}" << endl << endl;
284 s << "}" << endl << endl;
285 }
285 }
286
286
287 if (!meta_class->hasDefaultToStringFunction() && meta_class->hasToStringCapability()) {
287 if (meta_class->hasDefaultToStringFunction()) {
288 s << "QString PythonQtWrapper_" << meta_class->name() << "::py_toString(" << meta_class->qualifiedCppName() << "* obj) { return obj->toString(); }" << endl;
289 } else if (meta_class->hasToStringCapability()) {
288 FunctionModelItem fun = meta_class->hasToStringCapability();
290 FunctionModelItem fun = meta_class->hasToStringCapability();
289 int indirections = fun->arguments().at(1)->type().indirections();
291 int indirections = fun->arguments().at(1)->type().indirections();
290 QString deref = QLatin1String(indirections == 0 ? "*" : "");
292 QString deref = QLatin1String(indirections == 0 ? "*" : "");
291 s << "QString PythonQtWrapper_" << meta_class->name() << "::toString(" << meta_class->qualifiedCppName() << "* obj) {" << endl;
293 s << "QString PythonQtWrapper_" << meta_class->name() << "::py_toString(" << meta_class->qualifiedCppName() << "* obj) {" << endl;
292 s << " QString result;" << endl;
294 s << " QString result;" << endl;
293 s << " QDebug d(&result);" << endl;
295 s << " QDebug d(&result);" << endl;
294 s << " d << " << deref << "obj;" << endl;
296 s << " d << " << deref << "obj;" << endl;
295 s << " return result;" << endl;
297 s << " return result;" << endl;
296 s << "}" << endl << endl;
298 s << "}" << endl << endl;
297 }
299 }
298
300
299 }
301 }
300
302
301 void ShellImplGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
303 void ShellImplGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
302 {
304 {
303 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
305 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
304 foreach (const CodeSnip &cs, code_snips) {
306 foreach (const CodeSnip &cs, code_snips) {
305 if (cs.language == TypeSystem::ShellCode) {
307 if (cs.language == TypeSystem::ShellCode) {
306 s << cs.code() << endl;
308 s << cs.code() << endl;
307 }
309 }
308 }
310 }
309 }
311 }
General Comments 0
You need to be logged in to leave comments. Login now