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