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