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