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