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