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