comparison generator/abstractmetalang.cpp @ 1:e78566595089

initial import
author mandel
date Mon, 11 May 2009 16:01:50 +0000
parents
children a5cba313c924
comparison
equal deleted inserted replaced
0:36fb74dc547d 1:e78566595089
1 /****************************************************************************
2 **
3 ** Copyright (C) 1992-2008 Nokia. All rights reserved.
4 **
5 ** This file is part of Qt Jambi.
6 **
7 ** * Commercial Usage
8 * Licensees holding valid Qt Commercial licenses may use this file in
9 * accordance with the Qt Commercial License Agreement provided with the
10 * Software or, alternatively, in accordance with the terms contained in
11 * a written agreement between you and Nokia.
12 *
13 *
14 * GNU General Public License Usage
15 * Alternatively, this file may be used under the terms of the GNU
16 * General Public License versions 2.0 or 3.0 as published by the Free
17 * Software Foundation and appearing in the file LICENSE.GPL included in
18 * the packaging of this file. Please review the following information
19 * to ensure GNU General Public Licensing requirements will be met:
20 * http://www.fsf.org/licensing/licenses/info/GPLv2.html and
21 * http://www.gnu.org/copyleft/gpl.html. In addition, as a special
22 * exception, Nokia gives you certain additional rights. These rights
23 * are described in the Nokia Qt GPL Exception version 1.2, included in
24 * the file GPL_EXCEPTION.txt in this package.
25 *
26 * Qt for Windows(R) Licensees
27 * As a special exception, Nokia, as the sole copyright holder for Qt
28 * Designer, grants users of the Qt/Eclipse Integration plug-in the
29 * right for the Qt/Eclipse Integration to link to functionality
30 * provided by Qt Designer and its related libraries.
31 *
32 *
33 * If you are unsure which license is appropriate for your use, please
34 * contact the sales department at qt-sales@nokia.com.
35
36 **
37 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
38 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
39 **
40 ****************************************************************************/
41
42 #include "abstractmetalang.h"
43 #include "reporthandler.h"
44 #include "jumptable.h"
45
46 /*******************************************************************************
47 * AbstractMetaType
48 */
49 AbstractMetaType *AbstractMetaType::copy() const
50 {
51 AbstractMetaType *cpy = new AbstractMetaType;
52
53 cpy->setTypeUsagePattern(typeUsagePattern());
54 cpy->setConstant(isConstant());
55 cpy->setReference(isReference());
56 cpy->setIndirections(indirections());
57 cpy->setInstantiations(instantiations());
58 cpy->setArrayElementCount(arrayElementCount());
59 cpy->setOriginalTypeDescription(originalTypeDescription());
60 cpy->setOriginalTemplateType(originalTemplateType() ? originalTemplateType()->copy() : 0);
61
62 cpy->setArrayElementType(arrayElementType() ? arrayElementType()->copy() : 0);
63
64 cpy->setTypeEntry(typeEntry());
65
66 return cpy;
67 }
68
69 QString AbstractMetaType::cppSignature() const
70 {
71 QString s;
72
73 if (isConstant())
74 s += "const ";
75
76 s += typeEntry()->qualifiedCppName();
77
78 if (hasInstantiationInCpp()) {
79 QList<AbstractMetaType *> types = instantiations();
80 s += "<";
81 for (int i=0; i<types.count(); ++i) {
82 if (i > 0)
83 s += ", ";
84 s += types.at(i)->cppSignature();
85 }
86 s += " >";
87 }
88
89 if (actualIndirections()) {
90 s += ' ';
91 if (indirections())
92 s += QString(indirections(), '*');
93 if (isReference())
94 s += '&';
95 }
96 return s;
97 }
98
99 /*******************************************************************************
100 * AbstractMetaArgument
101 */
102 AbstractMetaArgument *AbstractMetaArgument::copy() const
103 {
104 AbstractMetaArgument *cpy = new AbstractMetaArgument;
105 cpy->setName(AbstractMetaVariable::name());
106 cpy->setDefaultValueExpression(defaultValueExpression());
107 cpy->setType(type()->copy());
108 cpy->setArgumentIndex(argumentIndex());
109
110 return cpy;
111 }
112
113
114 QString AbstractMetaArgument::argumentName() const
115 {
116 QString n = AbstractMetaVariable::name();
117 // replace for arguments which are D keywords such as "version"
118 n = ArgumentReplace::translate(n);
119
120 if (n.isEmpty()) {
121 return QString("arg__%2").arg(m_argument_index + 1);
122 }
123 return n;
124 }
125
126
127 QString AbstractMetaArgument::indexedName() const
128 {
129 QString n = AbstractMetaVariable::name();
130 if (n.isEmpty())
131 return argumentName();
132 return QString("%1%2").arg(n).arg(m_argument_index);
133 }
134
135 QString AbstractMetaArgument::name() const
136 {
137 Q_ASSERT_X(0, "AbstractMetaArgument::name()", "use argumentName() or indexedName() instead");
138 return QString();
139 }
140
141
142 /*******************************************************************************
143 * AbstractMetaFunction
144 */
145 AbstractMetaFunction::~AbstractMetaFunction()
146 {
147 qDeleteAll(m_arguments);
148 delete m_type;
149 }
150
151 /*******************************************************************************
152 * Indicates that this function has a modification that removes it
153 */
154 bool AbstractMetaFunction::isModifiedRemoved(int types) const
155 {
156 FunctionModificationList mods = modifications(implementingClass());
157 foreach (FunctionModification mod, mods) {
158 if (!mod.isRemoveModifier())
159 continue;
160
161 if ((mod.removal & types) == types)
162 return true;
163 }
164
165 return false;
166 }
167
168 bool AbstractMetaFunction::needsCallThrough() const
169 {
170 if (ownerClass()->isInterface())
171 return false;
172 if (referenceCounts(implementingClass()).size() > 0)
173 return true;
174 if (argumentsHaveNativeId() || !isStatic())
175 return true;
176 if (JumpTableGenerator::isJumpTableActive())
177 return true;
178
179 foreach (const AbstractMetaArgument *arg, arguments()) {
180 if (arg->type()->isArray() || arg->type()->isTargetLangEnum() || arg->type()->isTargetLangFlags())
181 return true;
182 }
183
184 if (type() && (type()->isArray() || type()->isTargetLangEnum() || type()->isTargetLangFlags()))
185 return true;
186
187 for (int i=-1; i<=arguments().size(); ++i) {
188 TypeSystem::Ownership owner = this->ownership(implementingClass(), TypeSystem::TargetLangCode, i);
189 if (owner != TypeSystem::InvalidOwnership)
190 return true;
191 }
192
193 return false;
194 }
195
196 bool AbstractMetaFunction::needsSuppressUncheckedWarning() const
197 {
198 for (int i=-1; i<=arguments().size(); ++i) {
199 QList<ReferenceCount> referenceCounts = this->referenceCounts(implementingClass(), i);
200 foreach (ReferenceCount referenceCount, referenceCounts) {
201 if (referenceCount.action != ReferenceCount::Set)
202 return true;
203 }
204 }
205 return false;
206 }
207
208 QString AbstractMetaFunction::marshalledName(bool classIsOwner) const
209 {
210 QString returned = "qtd_";
211 if(classIsOwner)
212 returned += ownerClass()->name();
213 else
214 returned += declaringClass()->name();
215
216 returned += "_" + name();
217 AbstractMetaArgumentList arguments = this->arguments();
218 foreach (const AbstractMetaArgument *arg, arguments) {
219 returned += "_";
220 if (arg->type()->isNativePointer()) {
221 returned += "nativepointer" + arg->type()->name().replace("[]", "_3").replace(".", "_");
222 } else if (arg->type()->isIntegerEnum() || arg->type()->isIntegerFlags()) {
223 returned += "int";
224 } else {
225 returned += arg->type()->name().replace("[]", "_3").replace(".", "_");
226 }
227 }
228 return returned;
229 }
230
231 bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const
232 {
233 uint result = compareTo(&other);
234 return result & NameLessThan;
235 }
236
237
238 /*!
239 Returns a mask of CompareResult describing how this function is
240 compares to another function
241 */
242 uint AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const
243 {
244 uint result = 0;
245
246 // Enclosing class...
247 if (ownerClass() == other->ownerClass()) {
248 result |= EqualImplementor;
249 }
250
251 // Attributes
252 if (attributes() == other->attributes()) {
253 result |= EqualAttributes;
254 }
255
256 // Compare types
257 AbstractMetaType *t = type();
258 AbstractMetaType *ot = other->type();
259 if ((!t && !ot) || ((t && ot && t->name() == ot->name()))) {
260 result |= EqualReturnType;
261 }
262
263 // Compare names
264 int cmp = originalName().compare(other->originalName());
265
266 if (cmp < 0) {
267 result |= NameLessThan;
268 } else if (cmp == 0) {
269 result |= EqualName;
270 }
271
272 // compare name after modification...
273 cmp = modifiedName().compare(other->modifiedName());
274 if (cmp == 0)
275 result |= EqualModifiedName;
276
277 // Compare arguments...
278 AbstractMetaArgumentList min_arguments;
279 AbstractMetaArgumentList max_arguments;
280 if (arguments().size() < other->arguments().size()) {
281 min_arguments = arguments();
282 max_arguments = other->arguments();
283 } else {
284 min_arguments = other->arguments();
285 max_arguments = arguments();
286 }
287
288 int min_count = min_arguments.size();
289 int max_count = max_arguments.size();
290 bool same = true;
291 for (int i=0; i<max_count; ++i) {
292 if (i < min_count) {
293 const AbstractMetaArgument *min_arg = min_arguments.at(i);
294 const AbstractMetaArgument *max_arg = max_arguments.at(i);
295 if (min_arg->type()->name() != max_arg->type()->name()
296 && (min_arg->defaultValueExpression().isEmpty() || max_arg->defaultValueExpression().isEmpty())) {
297 same = false;
298 break;
299 }
300 } else {
301 if (max_arguments.at(i)->defaultValueExpression().isEmpty()) {
302 same = false;
303 break;
304 }
305 }
306 }
307
308 if (same)
309 result |= min_count == max_count ? EqualArguments : EqualDefaultValueOverload;
310
311 return result;
312 }
313
314 AbstractMetaFunction *AbstractMetaFunction::copy() const
315 {
316 AbstractMetaFunction *cpy = new AbstractMetaFunction;
317 cpy->setName(name());
318 cpy->setOriginalName(originalName());
319 cpy->setOwnerClass(ownerClass());
320 cpy->setImplementingClass(implementingClass());
321 cpy->setInterfaceClass(interfaceClass());
322 cpy->setFunctionType(functionType());
323 cpy->setAttributes(attributes());
324 cpy->setDeclaringClass(declaringClass());
325 if (type())
326 cpy->setType(type()->copy());
327 cpy->setConstant(isConstant());
328 cpy->setOriginalAttributes(originalAttributes());
329
330 foreach (AbstractMetaArgument *arg, arguments())
331 cpy->addArgument(arg->copy());
332
333 Q_ASSERT((!type() && !cpy->type())
334 || (type()->instantiations() == cpy->type()->instantiations()));
335
336 return cpy;
337 }
338
339 QStringList AbstractMetaFunction::introspectionCompatibleSignatures(const QStringList &resolvedArguments) const
340 {
341 AbstractMetaArgumentList arguments = this->arguments();
342 if (arguments.size() == resolvedArguments.size()) {
343 return (QStringList() << QMetaObject::normalizedSignature((name() + "(" + resolvedArguments.join(",") + ")").toUtf8().constData()));
344 } else {
345 QStringList returned;
346
347 AbstractMetaArgument *argument = arguments.at(resolvedArguments.size());
348 QStringList minimalTypeSignature = argument->type()->minimalSignature().split("::");
349 for (int i=0; i<minimalTypeSignature.size(); ++i) {
350 returned += introspectionCompatibleSignatures(QStringList(resolvedArguments)
351 << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join("::"));
352 }
353
354 return returned;
355 }
356 }
357
358 QString AbstractMetaFunction::signature() const
359 {
360 QString s(m_original_name);
361
362 s += "(";
363
364 for (int i=0; i<m_arguments.count(); ++i) {
365 if (i > 0)
366 s += ", ";
367 AbstractMetaArgument *a = m_arguments.at(i);
368 s += a->type()->cppSignature();
369
370 // We need to have the argument names in the qdoc files
371 s += " ";
372 s += a->argumentName();
373 }
374 s += ")";
375
376 if (isConstant())
377 s += " const";
378
379 return s;
380 }
381
382 int AbstractMetaFunction::actualMinimumArgumentCount() const
383 {
384 AbstractMetaArgumentList arguments = this->arguments();
385
386 int count = 0;
387 for (int i=0; i<arguments.size(); ++i && ++count) {
388 if (argumentRemoved(i + 1)) --count;
389 else if (!arguments.at(i)->defaultValueExpression().isEmpty()) break;
390 }
391
392 return count;
393 }
394
395 // Returns reference counts for argument at idx, or all arguments if idx == -2
396 QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const
397 {
398 QList<ReferenceCount> returned;
399
400 FunctionModificationList mods = this->modifications(cls);
401 foreach (FunctionModification mod, mods) {
402 QList<ArgumentModification> argument_mods = mod.argument_mods;
403 foreach (ArgumentModification argument_mod, argument_mods) {
404 if (argument_mod.index != idx && idx != -2)
405 continue;
406 returned += argument_mod.referenceCounts;
407 }
408 }
409
410 return returned;
411 }
412
413 QString AbstractMetaFunction::replacedDefaultExpression(const AbstractMetaClass *cls, int key) const
414 {
415 FunctionModificationList modifications = this->modifications(cls);
416 foreach (FunctionModification modification, modifications) {
417 QList<ArgumentModification> argument_modifications = modification.argument_mods;
418 foreach (ArgumentModification argument_modification, argument_modifications) {
419 if (argument_modification.index == key
420 && !argument_modification.replaced_default_expression.isEmpty()) {
421 return argument_modification.replaced_default_expression;
422 }
423 }
424 }
425
426 return QString();
427 }
428
429 bool AbstractMetaFunction::removedDefaultExpression(const AbstractMetaClass *cls, int key) const
430 {
431 FunctionModificationList modifications = this->modifications(cls);
432 foreach (FunctionModification modification, modifications) {
433 QList<ArgumentModification> argument_modifications = modification.argument_mods;
434 foreach (ArgumentModification argument_modification, argument_modifications) {
435 if (argument_modification.index == key
436 && argument_modification.removed_default_expression) {
437 return true;
438 }
439 }
440 }
441
442 return false;
443 }
444
445 bool AbstractMetaFunction::resetObjectAfterUse(int argument_idx) const
446 {
447 const AbstractMetaClass *cls = declaringClass();
448 FunctionModificationList modifications = this->modifications(cls);
449 foreach (FunctionModification modification, modifications) {
450 QList<ArgumentModification> argumentModifications = modification.argument_mods;
451 foreach (ArgumentModification argumentModification, argumentModifications) {
452 if (argumentModification.index == argument_idx && argumentModification.reset_after_use)
453 return true;
454 }
455 }
456
457 return false;
458 }
459
460 QString AbstractMetaFunction::nullPointerDefaultValue(const AbstractMetaClass *mainClass, int argument_idx) const
461 {
462 Q_ASSERT(nullPointersDisabled(mainClass, argument_idx));
463
464 const AbstractMetaClass *cls = mainClass;
465 if (cls == 0)
466 cls = implementingClass();
467
468 do {
469 FunctionModificationList modifications = this->modifications(cls);
470 foreach (FunctionModification modification, modifications) {
471 QList<ArgumentModification> argument_modifications = modification.argument_mods;
472 foreach (ArgumentModification argument_modification, argument_modifications) {
473 if (argument_modification.index == argument_idx
474 && argument_modification.no_null_pointers) {
475 return argument_modification.null_pointer_default_value;
476 }
477 }
478 }
479
480 cls = cls->baseClass();
481 } while (cls != 0 && mainClass == 0); // Once when mainClass != 0, or once for all base classes of implementing class
482
483 return QString();
484
485 }
486
487 bool AbstractMetaFunction::nullPointersDisabled(const AbstractMetaClass *mainClass, int argument_idx) const
488 {
489 const AbstractMetaClass *cls = mainClass;
490 if (cls == 0)
491 cls = implementingClass();
492
493 do {
494 FunctionModificationList modifications = this->modifications(cls);
495 foreach (FunctionModification modification, modifications) {
496 QList<ArgumentModification> argument_modifications = modification.argument_mods;
497 foreach (ArgumentModification argument_modification, argument_modifications) {
498 if (argument_modification.index == argument_idx
499 && argument_modification.no_null_pointers) {
500 return true;
501 }
502 }
503 }
504
505 cls = cls->baseClass();
506 } while (cls != 0 && mainClass == 0); // Once when mainClass != 0, or once for all base classes of implementing class
507
508 return false;
509 }
510
511 QString AbstractMetaFunction::conversionRule(TypeSystem::Language language, int key) const
512 {
513 FunctionModificationList modifications = this->modifications(declaringClass());
514 foreach (FunctionModification modification, modifications) {
515 QList<ArgumentModification> argument_modifications = modification.argument_mods;
516 foreach (ArgumentModification argument_modification, argument_modifications) {
517 if (argument_modification.index != key)
518 continue;
519
520 foreach (CodeSnip snip, argument_modification.conversion_rules) {
521 if (snip.language == language && !snip.code().isEmpty())
522 return snip.code();
523 }
524 }
525 }
526
527 return QString();
528 }
529
530 QString AbstractMetaFunction::argumentReplaced(int key) const
531 {
532 FunctionModificationList modifications = this->modifications(declaringClass());
533 foreach (FunctionModification modification, modifications) {
534 QList<ArgumentModification> argument_modifications = modification.argument_mods;
535 foreach (ArgumentModification argument_modification, argument_modifications) {
536 if (argument_modification.index == key && !argument_modification.replace_value.isEmpty()) {
537 return argument_modification.replace_value;
538 }
539 }
540 }
541
542 return "";
543 }
544
545 bool AbstractMetaFunction::argumentRemoved(int key) const
546 {
547 FunctionModificationList modifications = this->modifications(declaringClass());
548 foreach (FunctionModification modification, modifications) {
549 QList<ArgumentModification> argument_modifications = modification.argument_mods;
550 foreach (ArgumentModification argument_modification, argument_modifications) {
551 if (argument_modification.index == key) {
552 if (argument_modification.removed) {
553 return true;
554 }
555 }
556 }
557 }
558
559 return false;
560 }
561
562 bool AbstractMetaFunction::storeResult() const
563 {
564 if (m_store_result == 2)
565 return true;
566 else
567 return false;
568 }
569
570 void AbstractMetaFunction::checkStoreResult()
571 {
572 FunctionModificationList modifications = this->modifications(declaringClass());
573 foreach (FunctionModification modification, modifications) {
574 if (modification.store_result) {
575 m_store_result = 2;
576 return;
577 }
578 }
579
580 m_store_result = 1;
581 }
582
583 bool AbstractMetaFunction::isVirtualSlot() const
584 {
585 FunctionModificationList modifications = this->modifications(declaringClass());
586 foreach (FunctionModification modification, modifications) {
587 if (modification.isVirtualSlot())
588 return true;
589 }
590
591 return false;
592 }
593
594 bool AbstractMetaFunction::disabledGarbageCollection(const AbstractMetaClass *cls, int key) const
595 {
596 FunctionModificationList modifications = this->modifications(cls);
597 foreach (FunctionModification modification, modifications) {
598 QList<ArgumentModification> argument_modifications = modification.argument_mods;
599 foreach (ArgumentModification argument_modification, argument_modifications) {
600 if (argument_modification.index != key)
601 continue;
602
603 foreach (TypeSystem::Ownership ownership, argument_modification.ownerships.values()) {
604 if (ownership == TypeSystem::CppOwnership)
605 return true;
606 }
607
608 }
609 }
610
611 return false;
612 }
613
614 bool AbstractMetaFunction::isDeprecated() const
615 {
616 FunctionModificationList modifications = this->modifications(declaringClass());
617 foreach (FunctionModification modification, modifications) {
618 if (modification.isDeprecated())
619 return true;
620 }
621 return false;
622 }
623
624 TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const
625 {
626 FunctionModificationList modifications = this->modifications(cls);
627 foreach (FunctionModification modification, modifications) {
628 QList<ArgumentModification> argument_modifications = modification.argument_mods;
629 foreach (ArgumentModification argument_modification, argument_modifications) {
630 if (argument_modification.index == key)
631 return argument_modification.ownerships.value(language, TypeSystem::InvalidOwnership);
632 }
633 }
634
635 return TypeSystem::InvalidOwnership;
636 }
637
638 bool AbstractMetaFunction::isRemovedFromAllLanguages(const AbstractMetaClass *cls) const
639 {
640 return isRemovedFrom(cls, TypeSystem::All);
641 }
642
643 bool AbstractMetaFunction::isRemovedFrom(const AbstractMetaClass *cls, TypeSystem::Language language) const
644 {
645 FunctionModificationList modifications = this->modifications(cls);
646 foreach (FunctionModification modification, modifications) {
647 if ((modification.removal & language) == language)
648 return true;
649 }
650
651 return false;
652
653 }
654
655 QString AbstractMetaFunction::typeReplaced(int key) const
656 {
657 FunctionModificationList modifications = this->modifications(declaringClass());
658 foreach (FunctionModification modification, modifications) {
659 QList<ArgumentModification> argument_modifications = modification.argument_mods;
660 foreach (ArgumentModification argument_modification, argument_modifications) {
661 if (argument_modification.index == key
662 && !argument_modification.modified_type.isEmpty()) {
663 return argument_modification.modified_type;
664 }
665 }
666 }
667
668 return QString();
669 }
670
671 QString AbstractMetaFunction::minimalSignature() const
672 {
673 if (!m_cached_minimal_signature.isEmpty())
674 return m_cached_minimal_signature;
675
676 QString minimalSignature = originalName() + "(";
677 AbstractMetaArgumentList arguments = this->arguments();
678
679 for (int i=0; i<arguments.count(); ++i) {
680 AbstractMetaType *t = arguments.at(i)->type();
681
682 if (i > 0)
683 minimalSignature += ",";
684
685 minimalSignature += t->minimalSignature();
686 }
687 minimalSignature += ")";
688 if (isConstant())
689 minimalSignature += "const";
690
691 minimalSignature = QMetaObject::normalizedSignature(minimalSignature.toLocal8Bit().constData());
692 m_cached_minimal_signature = minimalSignature;
693
694 return minimalSignature;
695 }
696
697 FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass *implementor) const
698 {
699 Q_ASSERT(implementor);
700 return implementor->typeEntry()->functionModifications(minimalSignature());
701 }
702
703 bool AbstractMetaFunction::hasModifications(const AbstractMetaClass *implementor) const
704 {
705 FunctionModificationList mods = modifications(implementor);
706 return mods.count() > 0;
707 }
708
709 QString AbstractMetaFunction::modifiedName() const
710 {
711 if (m_cached_modified_name.isEmpty()) {
712 FunctionModificationList mods = modifications(implementingClass());
713 foreach (FunctionModification mod, mods) {
714 if (mod.isRenameModifier()) {
715 m_cached_modified_name = mod.renamedToName;
716 break;
717 }
718 }
719 if (m_cached_modified_name.isEmpty())
720 m_cached_modified_name = name();
721 }
722 return m_cached_modified_name;
723 }
724
725 QString AbstractMetaFunction::targetLangSignature(bool minimal) const
726 {
727 QString s;
728
729 // Attributes...
730 if (!minimal) {
731 if (isPublic()) s += "public ";
732 else if (isProtected()) s += "protected ";
733 else if (isPrivate()) s += "private ";
734
735 // if (isNative()) s += "native ";
736 // else
737 if (isFinalInTargetLang()) s += "final ";
738 else if (isAbstract()) s += "abstract ";
739
740 if (isStatic()) s += "static ";
741
742 // Return type
743 if (type())
744 s += type()->fullName() + " ";
745 else
746 s += "void ";
747 }
748
749 s += name();
750 s += "(";
751
752 for (int i=0; i<m_arguments.size(); ++i) {
753 if (i != 0) {
754 s += ",";
755 if (!minimal)
756 s += QLatin1Char(' ');
757 }
758 s += m_arguments.at(i)->type()->fullName();
759
760 if (!minimal) {
761 s += " ";
762 s += m_arguments.at(i)->argumentName();
763 }
764 }
765
766 s += ")";
767
768 return s;
769 }
770
771
772 bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b)
773 {
774 return a->signature() < b->signature();
775 }
776
777 /*******************************************************************************
778 * AbstractMetaClass
779 */
780 AbstractMetaClass::~AbstractMetaClass()
781 {
782 qDeleteAll(m_functions);
783 qDeleteAll(m_fields);
784 }
785
786 /*AbstractMetaClass *AbstractMetaClass::copy() const
787 {
788 AbstractMetaClass *cls = new AbstractMetaClass;
789 cls->setAttributes(attributes());
790 cls->setBaseClass(baseClass());
791 cls->setTypeEntry(typeEntry());
792 foreach (AbstractMetaFunction *function, functions()) {
793 AbstractMetaFunction *copy = function->copy();
794 function->setImplementingClass(cls);
795 cls->addFunction(copy);
796 }
797 cls->setEnums(enums());
798 foreach (const AbstractMetaField *field, fields()) {
799 AbstractMetaField *copy = field->copy();
800 copy->setEnclosingClass(cls);
801 cls->addField(copy);
802 }
803 cls->setInterfaces(interfaces());
804
805 return cls;
806 }*/
807
808 /*******************************************************************************
809 * Returns true if this class is a subclass of the given class
810 */
811 bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const
812 {
813 Q_ASSERT(cls != 0);
814
815 const AbstractMetaClass *clazz = this;
816 while (clazz != 0) {
817 if (clazz == cls)
818 return true;
819
820 clazz = clazz->baseClass();
821 }
822
823 return false;
824 }
825
826 /*******************************************************************************
827 * Constructs an interface based on the functions and enums in this
828 * class and returns it...
829 */
830 AbstractMetaClass *AbstractMetaClass::extractInterface()
831 {
832 Q_ASSERT(typeEntry()->designatedInterface());
833
834 if (m_extracted_interface == 0) {
835 AbstractMetaClass *iface = new AbstractMetaClass;
836 iface->setAttributes(attributes());
837 iface->setBaseClass(0);
838 iface->setPrimaryInterfaceImplementor(this);
839
840 iface->setTypeEntry(typeEntry()->designatedInterface());
841
842 foreach (AbstractMetaFunction *function, functions()) {
843 if (!function->isConstructor())
844 iface->addFunction(function->copy());
845 }
846
847 // iface->setEnums(enums());
848 // setEnums(AbstractMetaEnumList());
849
850 foreach (const AbstractMetaField *field, fields()) {
851 if (field->isPublic()) {
852 AbstractMetaField *new_field = field->copy();
853 new_field->setEnclosingClass(iface);
854 iface->addField(new_field);
855 }
856 }
857
858 m_extracted_interface = iface;
859 addInterface(iface);
860 }
861
862 return m_extracted_interface;
863 }
864
865 /*******************************************************************************
866 * Returns a list of all the functions with a given name
867 */
868 AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const
869 {
870 AbstractMetaFunctionList returned;
871 AbstractMetaFunctionList functions = this->functions();
872 foreach (AbstractMetaFunction *function, functions) {
873 if (function->name() == name)
874 returned.append(function);
875 }
876
877 return returned;
878 }
879
880 /*******************************************************************************
881 * Returns all reference count modifications for any function in the class
882 */
883 QList<ReferenceCount> AbstractMetaClass::referenceCounts() const
884 {
885 QList<ReferenceCount> returned;
886
887 AbstractMetaFunctionList functions = this->functions();
888 foreach (AbstractMetaFunction *function, functions) {
889 returned += function->referenceCounts(this);
890 }
891
892 return returned;
893 }
894
895 /*******************************************************************************
896 * Returns a list of all the functions retrieved during parsing which should
897 * be added to the Java API.
898 */
899 AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const
900 {
901 int default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang;
902
903 // Interfaces don't implement functions
904 default_flags |= isInterface() ? 0 : ClassImplements;
905
906 // Only public functions in final classes
907 // default_flags |= isFinal() ? WasPublic : 0;
908 int public_flags = isFinal() ? WasPublic : 0;
909
910 // Constructors
911 AbstractMetaFunctionList returned = queryFunctions(Constructors | default_flags | public_flags);
912
913 // Final functions
914 returned += queryFunctions(FinalInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags);
915
916 // Virtual functions
917 returned += queryFunctions(VirtualInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags);
918
919 // Static functions
920 returned += queryFunctions(StaticFunctions | default_flags | public_flags);
921
922 // Empty, private functions, since they aren't caught by the other ones
923 returned += queryFunctions(Empty | Invisible);
924
925 return returned;
926 }
927
928 AbstractMetaFunctionList AbstractMetaClass::virtualFunctions() const
929 {
930 AbstractMetaFunctionList list = functionsInShellClass();
931
932 AbstractMetaFunctionList returned;
933 foreach (AbstractMetaFunction *f, list) {
934 if (!f->isFinalInCpp() || f->isVirtualSlot())
935 returned += f;
936 }
937
938 return returned;
939 }
940
941 AbstractMetaFunctionList AbstractMetaClass::nonVirtualShellFunctions() const
942 {
943 AbstractMetaFunctionList list = functionsInShellClass();
944 AbstractMetaFunctionList returned;
945 foreach (AbstractMetaFunction *f, list) {
946 if (f->isFinalInCpp() && !f->isVirtualSlot())
947 returned += f;
948 }
949
950 return returned;
951 }
952
953 /*******************************************************************************
954 * Returns a list of all functions that should be declared and implemented in
955 * the shell class which is generated as a wrapper on top of the actual C++ class
956 */
957 AbstractMetaFunctionList AbstractMetaClass::functionsInShellClass() const
958 {
959 // Only functions and only protected and public functions
960 int default_flags = NormalFunctions | Visible | WasVisible | NotRemovedFromShell;
961
962 // All virtual functions
963 AbstractMetaFunctionList returned = queryFunctions(VirtualFunctions | default_flags);
964
965 // All functions explicitly set to be implemented by the shell class
966 // (mainly superclass functions that are hidden by other declarations)
967 returned += queryFunctions(ForcedShellFunctions | default_flags);
968
969 // All functions explicitly set to be virtual slots
970 returned += queryFunctions(VirtualSlots | default_flags);
971
972 return returned;
973 }
974
975 /*******************************************************************************
976 * Returns a list of all functions that require a public override function to
977 * be generated in the shell class. This includes all functions that were originally
978 * protected in the superclass.
979 */
980 AbstractMetaFunctionList AbstractMetaClass::publicOverrideFunctions() const
981 {
982 return queryFunctions(NormalFunctions | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang)
983 + queryFunctions(Signals | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang);
984 }
985
986 AbstractMetaFunctionList AbstractMetaClass::virtualOverrideFunctions() const
987 {
988 return queryFunctions(NormalFunctions | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell) +
989 queryFunctions(Signals | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell);
990 }
991
992 void AbstractMetaClass::sortFunctions()
993 {
994 qSort(m_functions.begin(), m_functions.end(), function_sorter);
995 }
996
997 void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions)
998 {
999 m_functions = functions;
1000
1001 // Functions must be sorted by name before next loop
1002 sortFunctions();
1003
1004 QString currentName;
1005 bool hasVirtuals = false;
1006 AbstractMetaFunctionList final_functions;
1007 foreach (AbstractMetaFunction *f, m_functions) {
1008 f->setOwnerClass(this);
1009
1010 m_has_virtual_slots |= f->isVirtualSlot();
1011 m_has_virtuals |= !f->isFinal() || f->isVirtualSlot();
1012 m_has_nonpublic |= !f->isPublic();
1013
1014 // If we have non-virtual overloads of a virtual function, we have to implement
1015 // all the overloads in the shell class to override the hiding rule
1016 if (currentName == f->name()) {
1017 hasVirtuals = hasVirtuals || !f->isFinal();
1018 if (f->isFinal())
1019 final_functions += f;
1020 } else {
1021 if (hasVirtuals && final_functions.size() > 0) {
1022 foreach (AbstractMetaFunction *final_function, final_functions) {
1023 *final_function += AbstractMetaAttributes::ForceShellImplementation;
1024
1025 QString warn = QString("hiding of function '%1' in class '%2'")
1026 .arg(final_function->name()).arg(name());
1027 ReportHandler::warning(warn);
1028 }
1029 }
1030
1031 hasVirtuals = !f->isFinal();
1032 final_functions.clear();
1033 if (f->isFinal())
1034 final_functions += f;
1035 currentName = f->name();
1036 }
1037 }
1038
1039 #ifndef QT_NO_DEBUG
1040 bool duplicate_function = false;
1041 for (int j=0; j<m_functions.size(); ++j) {
1042 FunctionModificationList mods = m_functions.at(j)->modifications(m_functions.at(j)->implementingClass());
1043
1044 bool removed = false;
1045 foreach (const FunctionModification &mod, mods) {
1046 if (mod.isRemoveModifier()) {
1047 removed = true;
1048 break ;
1049 }
1050 }
1051 if (removed)
1052 continue ;
1053
1054 for (int i=0; i<m_functions.size() - 1; ++i) {
1055 if (j == i)
1056 continue;
1057
1058 mods = m_functions.at(i)->modifications(m_functions.at(i)->implementingClass());
1059 bool removed = false;
1060 foreach (const FunctionModification &mod, mods) {
1061 if (mod.isRemoveModifier()) {
1062 removed = true;
1063 break ;
1064 }
1065 }
1066 if (removed)
1067 continue ;
1068
1069 uint cmp = m_functions.at(i)->compareTo(m_functions.at(j));
1070 if ((cmp & AbstractMetaFunction::EqualName) && (cmp & AbstractMetaFunction::EqualArguments)) {
1071 printf("%s.%s mostly equal to %s.%s\n",
1072 qPrintable(m_functions.at(i)->implementingClass()->typeEntry()->qualifiedCppName()),
1073 qPrintable(m_functions.at(i)->signature()),
1074 qPrintable(m_functions.at(j)->implementingClass()->typeEntry()->qualifiedCppName()),
1075 qPrintable(m_functions.at(j)->signature()));
1076 duplicate_function = true;
1077 }
1078 }
1079 }
1080 //Q_ASSERT(!duplicate_function);
1081 #endif
1082 }
1083
1084 bool AbstractMetaClass::hasFieldAccessors() const
1085 {
1086 foreach (const AbstractMetaField *field, fields()) {
1087 if (field->getter() || field->setter())
1088 return true;
1089 }
1090
1091 return false;
1092 }
1093
1094 bool AbstractMetaClass::hasDefaultToStringFunction() const
1095 {
1096 foreach (AbstractMetaFunction *f, queryFunctionsByName("toString")) {
1097 if (f->actualMinimumArgumentCount() == 0) {
1098 return true;
1099 }
1100
1101 }
1102 return false;
1103 }
1104
1105 void AbstractMetaClass::addFunction(AbstractMetaFunction *function)
1106 {
1107 function->setOwnerClass(this);
1108
1109 if (!function->isDestructor()) {
1110 m_functions << function;
1111 qSort(m_functions.begin(), m_functions.end(), function_sorter);
1112 }
1113
1114
1115 m_has_virtual_slots |= function->isVirtualSlot();
1116 m_has_virtuals |= !function->isFinal() || function->isVirtualSlot();
1117 m_has_nonpublic |= !function->isPublic();
1118 }
1119
1120 bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const
1121 {
1122 if (!other->isSignal())
1123 return false;
1124
1125 foreach (const AbstractMetaFunction *f, functions()) {
1126 if (f->isSignal() && f->compareTo(other) & AbstractMetaFunction::EqualName)
1127 return other->modifiedName() == f->modifiedName();
1128 }
1129
1130 return false;
1131 }
1132
1133
1134 QString AbstractMetaClass::name() const
1135 {
1136 return QString(m_type_entry->targetLangName()).replace("::", "_");
1137 }
1138
1139 bool AbstractMetaClass::hasFunction(const QString &str) const
1140 {
1141 foreach (const AbstractMetaFunction *f, functions())
1142 if (f->name() == str)
1143 return true;
1144 return false;
1145 }
1146
1147 /* Returns true if this class has one or more functions that are
1148 protected. If a class has protected members we need to generate a
1149 shell class with public accessors to the protected functions, so
1150 they can be called from the native functions.
1151 */
1152 bool AbstractMetaClass::hasProtectedFunctions() const {
1153 foreach (AbstractMetaFunction *func, m_functions) {
1154 if (func->isProtected())
1155 return true;
1156 }
1157 return false;
1158 }
1159
1160 bool AbstractMetaClass::generateShellClass() const
1161 {
1162 return m_force_shell_class ||
1163 (!isFinal()
1164 && (hasVirtualFunctions()
1165 || hasProtectedFunctions()
1166 || hasFieldAccessors()
1167 || typeEntry()->isObject())); // qtd2 for being more consistent
1168 }
1169
1170 QPropertySpec *AbstractMetaClass::propertySpecForRead(const QString &name) const
1171 {
1172 for (int i=0; i<m_property_specs.size(); ++i)
1173 if (name == m_property_specs.at(i)->read())
1174 return m_property_specs.at(i);
1175 return 0;
1176 }
1177
1178 QPropertySpec *AbstractMetaClass::propertySpecForWrite(const QString &name) const
1179 {
1180 for (int i=0; i<m_property_specs.size(); ++i)
1181 if (name == m_property_specs.at(i)->write())
1182 return m_property_specs.at(i);
1183 return 0;
1184 }
1185
1186 QPropertySpec *AbstractMetaClass::propertySpecForReset(const QString &name) const
1187 {
1188 for (int i=0; i<m_property_specs.size(); ++i) {
1189 if (name == m_property_specs.at(i)->reset())
1190 return m_property_specs.at(i);
1191 }
1192 return 0;
1193 }
1194
1195
1196
1197 static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func)
1198 {
1199 foreach (const AbstractMetaFunction *f, l) {
1200 if ((f->compareTo(func) & AbstractMetaFunction::PrettySimilar) == AbstractMetaFunction::PrettySimilar)
1201 return true;
1202 }
1203 return false;
1204 }
1205
1206 AbstractMetaField::AbstractMetaField() : m_getter(0), m_setter(0), m_class(0)
1207 {
1208 }
1209
1210 AbstractMetaField::~AbstractMetaField()
1211 {
1212 delete m_setter;
1213 delete m_getter;
1214 }
1215 ushort painters; // refcount
1216 AbstractMetaField *AbstractMetaField::copy() const
1217 {
1218 AbstractMetaField *returned = new AbstractMetaField;
1219 returned->setEnclosingClass(0);
1220 returned->setAttributes(attributes());
1221 returned->setName(name());
1222 returned->setType(type()->copy());
1223 returned->setOriginalAttributes(originalAttributes());
1224
1225 return returned;
1226 }
1227
1228 static QString upCaseFirst(const QString &str) {
1229 Q_ASSERT(!str.isEmpty());
1230 QString s = str;
1231 s[0] = s.at(0).toUpper();
1232 return s;
1233 }
1234
1235 static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QString &name, uint type) {
1236 AbstractMetaFunction *f = new AbstractMetaFunction;
1237
1238
1239
1240 f->setName(name);
1241 f->setOriginalName(name);
1242 f->setOwnerClass(g->enclosingClass());
1243 f->setImplementingClass(g->enclosingClass());
1244 f->setDeclaringClass(g->enclosingClass());
1245
1246 uint attr = AbstractMetaAttributes::Native
1247 | AbstractMetaAttributes::Final
1248 | type;
1249 if (g->isStatic())
1250 attr |= AbstractMetaAttributes::Static;
1251 if (g->isPublic())
1252 attr |= AbstractMetaAttributes::Public;
1253 else if (g->isProtected())
1254 attr |= AbstractMetaAttributes::Protected;
1255 else
1256 attr |= AbstractMetaAttributes::Private;
1257 f->setAttributes(attr);
1258 f->setOriginalAttributes(attr);
1259
1260 FieldModificationList mods = g->modifications();
1261 foreach (FieldModification mod, mods) {
1262 if (mod.isRenameModifier())
1263 f->setName(mod.renamedTo());
1264 if (mod.isAccessModifier()) {
1265 if (mod.isPrivate())
1266 f->setVisibility(AbstractMetaAttributes::Private);
1267 else if (mod.isProtected())
1268 f->setVisibility(AbstractMetaAttributes::Protected);
1269 else if (mod.isPublic())
1270 f->setVisibility(AbstractMetaAttributes::Public);
1271 else if (mod.isFriendly())
1272 f->setVisibility(AbstractMetaAttributes::Friendly);
1273 }
1274
1275 }
1276 return f;
1277 }
1278
1279 FieldModificationList AbstractMetaField::modifications() const
1280 {
1281 FieldModificationList mods = enclosingClass()->typeEntry()->fieldModifications();
1282 FieldModificationList returned;
1283
1284 foreach (FieldModification mod, mods) {
1285 if (mod.name == name())
1286 returned += mod;
1287 }
1288
1289 return returned;
1290 }
1291
1292 const AbstractMetaFunction *AbstractMetaField::setter() const
1293 {
1294 if (m_setter == 0) {
1295 m_setter = createXetter(this,
1296 "set" + upCaseFirst(name()),
1297 AbstractMetaAttributes::SetterFunction);
1298 AbstractMetaArgumentList arguments;
1299 AbstractMetaArgument *argument = new AbstractMetaArgument;
1300 argument->setType(type()->copy());
1301 argument->setName(name());
1302 arguments.append(argument);
1303 m_setter->setArguments(arguments);
1304 }
1305 return m_setter;
1306 }
1307
1308 const AbstractMetaFunction *AbstractMetaField::getter() const
1309 {
1310 if (m_getter == 0) {
1311 m_getter = createXetter(this,
1312 name(),
1313 AbstractMetaAttributes::GetterFunction);
1314 m_getter->setType(type());
1315 }
1316
1317 return m_getter;
1318 }
1319
1320
1321 bool AbstractMetaClass::hasConstructors() const
1322 {
1323 return queryFunctions(Constructors).size() != 0;
1324 }
1325
1326 void AbstractMetaClass::addDefaultConstructor()
1327 {
1328 AbstractMetaFunction *f = new AbstractMetaFunction;
1329 f->setName(name());
1330 f->setOwnerClass(this);
1331 f->setFunctionType(AbstractMetaFunction::ConstructorFunction);
1332 f->setArguments(AbstractMetaArgumentList());
1333 f->setDeclaringClass(this);
1334
1335 uint attr = AbstractMetaAttributes::Native;
1336 attr |= AbstractMetaAttributes::Public;
1337 attr |= AbstractMetaAttributes::Final; // qtd otherwise added constructor is virtual which in fact it is not
1338 f->setAttributes(attr);
1339 f->setImplementingClass(this);
1340 f->setOriginalAttributes(f->attributes());
1341
1342 addFunction(f);
1343 }
1344
1345 bool AbstractMetaClass::hasFunction(const AbstractMetaFunction *f) const
1346 {
1347 return functions_contains(m_functions, f);
1348 }
1349
1350 /* Goes through the list of functions and returns a list of all
1351 functions matching all of the criteria in \a query.
1352 */
1353
1354 AbstractMetaFunctionList AbstractMetaClass::queryFunctions(uint query) const
1355 {
1356 AbstractMetaFunctionList functions;
1357
1358 foreach (AbstractMetaFunction *f, m_functions) {
1359
1360 if ((query & VirtualSlots) && !f->isVirtualSlot())
1361 continue;
1362
1363 if ((query & NotRemovedFromTargetLang) && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode)) {
1364 continue;
1365 }
1366
1367 if ((query & NotRemovedFromTargetLang) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode)) {
1368 continue;
1369 }
1370
1371 if ((query & NotRemovedFromShell) && f->isRemovedFrom(f->implementingClass(), TypeSystem::ShellCode)) {
1372 continue;
1373 }
1374
1375 if ((query & NotRemovedFromShell) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::ShellCode)) {
1376 continue;
1377 }
1378
1379 if ((query & Visible) && f->isPrivate()) {
1380 continue;
1381 }
1382
1383 if ((query & VirtualInTargetLangFunctions) && f->isFinalInTargetLang()) {
1384 continue;
1385 }
1386
1387 if ((query & Invisible) && !f->isPrivate()) {
1388 continue;
1389 }
1390
1391 if ((query & Empty) && !f->isEmptyFunction()) {
1392 continue;
1393 }
1394
1395 if ((query & WasPublic) && !f->wasPublic()) {
1396 continue;
1397 }
1398
1399 if ((query & WasVisible) && f->wasPrivate()) {
1400 continue;
1401 }
1402
1403 if ((query & WasProtected) && !f->wasProtected()) {
1404 continue;
1405 }
1406
1407 if ((query & ClassImplements) && f->ownerClass() != f->implementingClass()) {
1408 continue;
1409 }
1410
1411 if ((query & Inconsistent) && (f->isFinalInTargetLang() || !f->isFinalInCpp() || f->isStatic())) {
1412 continue;
1413 }
1414
1415 if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang()) {
1416 continue;
1417 }
1418
1419 if ((query & FinalInCppFunctions) && !f->isFinalInCpp()) {
1420 continue;
1421 }
1422
1423 if ((query & VirtualInCppFunctions) && f->isFinalInCpp()) {
1424 continue;
1425 }
1426
1427 if ((query & Signals) && (!f->isSignal())) {
1428 continue;
1429 }
1430
1431 if ((query & ForcedShellFunctions)
1432 && (!f->isForcedShellImplementation()
1433 || !f->isFinal())) {
1434 continue;
1435 }
1436
1437 if ((query & Constructors) && (!f->isConstructor()
1438 || f->ownerClass() != f->implementingClass())
1439 || f->isConstructor() && (query & Constructors) == 0) {
1440 continue;
1441 }
1442
1443 // Destructors are never included in the functions of a class currently
1444 /*
1445 if ((query & Destructors) && (!f->isDestructor()
1446 || f->ownerClass() != f->implementingClass())
1447 || f->isDestructor() && (query & Destructors) == 0) {
1448 continue;
1449 }*/
1450
1451 if ((query & VirtualFunctions) && (f->isFinal() || f->isSignal() || f->isStatic())) {
1452 continue;
1453 }
1454
1455 if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal())) {
1456 continue;
1457 }
1458
1459 if ((query & NonStaticFunctions) && (f->isStatic())) {
1460 continue;
1461 }
1462
1463 if ((query & NonEmptyFunctions) && (f->isEmptyFunction())) {
1464 continue;
1465 }
1466
1467 if ((query & NormalFunctions) && (f->isSignal())) {
1468 continue;
1469 }
1470
1471 if ((query & AbstractFunctions) && !f->isAbstract()) {
1472 continue;
1473 }
1474
1475 functions << f;
1476 }
1477
1478 // qDebug() << "queried" << m_type_entry->qualifiedCppName() << "got" << functions.size() << "out of" << m_functions.size();
1479
1480 return functions;
1481 }
1482
1483
1484 bool AbstractMetaClass::hasInconsistentFunctions() const
1485 {
1486 return cppInconsistentFunctions().size() > 0;
1487 }
1488
1489 bool AbstractMetaClass::hasSignals() const
1490 {
1491 return cppSignalFunctions().size() > 0;
1492 }
1493
1494
1495 /**
1496 * Adds the specified interface to this class by adding all the
1497 * functions in the interface to this class.
1498 */
1499 void AbstractMetaClass::addInterface(AbstractMetaClass *interface)
1500 {
1501 Q_ASSERT(!m_interfaces.contains(interface));
1502 m_interfaces << interface;
1503
1504 if (m_extracted_interface != 0 && m_extracted_interface != interface)
1505 m_extracted_interface->addInterface(interface);
1506
1507 foreach (AbstractMetaFunction *function, interface->functions())
1508 if (!hasFunction(function) && !function->isConstructor()) {
1509 AbstractMetaFunction *cpy = function->copy();
1510 cpy->setImplementingClass(this);
1511
1512 // Setup that this function is an interface class.
1513 cpy->setInterfaceClass(interface);
1514 *cpy += AbstractMetaAttributes::InterfaceFunction;
1515
1516 // Copy the modifications in interface into the implementing classes.
1517 FunctionModificationList mods = function->modifications(interface);
1518 foreach (const FunctionModification &mod, mods) {
1519 m_type_entry->addFunctionModification(mod);
1520 }
1521
1522 // It should be mostly safe to assume that when we implement an interface
1523 // we don't "pass on" pure virtual functions to our sublcasses...
1524 // *cpy -= AbstractMetaAttributes::Abstract;
1525
1526 addFunction(cpy);
1527 }
1528 }
1529
1530
1531 void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces)
1532 {
1533 m_interfaces = interfaces;
1534 }
1535
1536
1537 AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName)
1538 {
1539 foreach (AbstractMetaEnum *e, m_enums) {
1540 if (e->name() == enumName)
1541 return e;
1542 }
1543
1544 if (typeEntry()->designatedInterface())
1545 return extractInterface()->findEnum(enumName);
1546
1547 return 0;
1548 }
1549
1550
1551
1552
1553 /*! Recursivly searches for the enum value named \a enumValueName in
1554 this class and its superclasses and interfaces. Values belonging to
1555 \a meta_enum are excluded from the search.
1556 */
1557 AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValueName, AbstractMetaEnum *meta_enum)
1558 {
1559 foreach (AbstractMetaEnum *e, m_enums) {
1560 if (e == meta_enum)
1561 continue;
1562 foreach (AbstractMetaEnumValue *v, e->values()) {
1563 if (v->name() == enumValueName)
1564 return v;
1565 }
1566 }
1567
1568 if (typeEntry()->designatedInterface())
1569 return extractInterface()->findEnumValue(enumValueName, meta_enum);
1570
1571 if (baseClass() != 0)
1572 return baseClass()->findEnumValue(enumValueName, meta_enum);
1573
1574 return 0;
1575 }
1576
1577
1578 /*!
1579 * Searches through all of this class' enums for a value matching the
1580 * name \a enumValueName. The name is excluding the class/namespace
1581 * prefix. The function recursivly searches interfaces and baseclasses
1582 * of this class.
1583 */
1584 AbstractMetaEnum *AbstractMetaClass::findEnumForValue(const QString &enumValueName)
1585 {
1586 foreach (AbstractMetaEnum *e, m_enums) {
1587 foreach (AbstractMetaEnumValue *v, e->values()) {
1588 if (v->name() == enumValueName)
1589 return e;
1590 }
1591 }
1592
1593 if (typeEntry()->designatedInterface())
1594 return extractInterface()->findEnumForValue(enumValueName);
1595
1596 if (baseClass() != 0)
1597 return baseClass()->findEnumForValue(enumValueName);
1598
1599 return 0;
1600 }
1601
1602
1603 static void add_extra_include_for_type(AbstractMetaClass *meta_class, const AbstractMetaType *type)
1604 {
1605
1606 if (type == 0)
1607 return;
1608
1609 Q_ASSERT(meta_class != 0);
1610 const TypeEntry *entry = (type ? type->typeEntry() : 0);
1611 if (entry != 0 && entry->isComplex()) {
1612 const ComplexTypeEntry *centry = static_cast<const ComplexTypeEntry *>(entry);
1613 ComplexTypeEntry *class_entry = meta_class->typeEntry();
1614 if (class_entry != 0 && centry->include().isValid())
1615 class_entry->addExtraInclude(centry->include());
1616 }
1617
1618 if (type->hasInstantiations()) {
1619 QList<AbstractMetaType *> instantiations = type->instantiations();
1620 foreach (AbstractMetaType *instantiation, instantiations)
1621 add_extra_include_for_type(meta_class, instantiation);
1622 }
1623 }
1624
1625 static void add_extra_includes_for_function(AbstractMetaClass *meta_class, const AbstractMetaFunction *meta_function)
1626 {
1627 Q_ASSERT(meta_class != 0);
1628 Q_ASSERT(meta_function != 0);
1629 add_extra_include_for_type(meta_class, meta_function->type());
1630
1631 AbstractMetaArgumentList arguments = meta_function->arguments();
1632 foreach (AbstractMetaArgument *argument, arguments)
1633 add_extra_include_for_type(meta_class, argument->type());
1634 }
1635
1636 void AbstractMetaClass::fixFunctions()
1637 {
1638 if (m_functions_fixed)
1639 return;
1640 else
1641 m_functions_fixed = true;
1642
1643 AbstractMetaClass *super_class = baseClass();
1644 AbstractMetaFunctionList funcs = functions();
1645
1646 // printf("fix functions for %s\n", qPrintable(name()));
1647
1648 if (super_class != 0)
1649 super_class->fixFunctions();
1650 int iface_idx = 0;
1651 while (super_class || iface_idx < interfaces().size()) {
1652 // printf(" - base: %s\n", qPrintable(super_class->name()));
1653
1654 // Since we always traverse the complete hierarchy we are only
1655 // interrested in what each super class implements, not what
1656 // we may have propagated from their base classes again.
1657 AbstractMetaFunctionList super_funcs;
1658 if (super_class) {
1659
1660 // Super classes can never be final
1661 if (super_class->isFinalInTargetLang()) {
1662 ReportHandler::warning("Final class '" + super_class->name() + "' set to non-final, as it is extended by other classes");
1663 *super_class -= AbstractMetaAttributes::FinalInTargetLang;
1664 }
1665 super_funcs = super_class->queryFunctions(AbstractMetaClass::ClassImplements);
1666 } else {
1667 super_funcs = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::NormalFunctions);
1668 }
1669
1670 QSet<AbstractMetaFunction *> funcs_to_add;
1671 for (int sfi=0; sfi<super_funcs.size(); ++sfi) {
1672 AbstractMetaFunction *sf = super_funcs.at(sfi);
1673
1674 if (sf->isRemovedFromAllLanguages(sf->implementingClass()))
1675 continue;
1676
1677 // we generally don't care about private functions, but we have to get the ones that are
1678 // virtual in case they override abstract functions.
1679 bool add = (sf->isNormal() || sf->isSignal() || sf->isEmptyFunction());
1680 for (int fi=0; fi<funcs.size(); ++fi) {
1681 AbstractMetaFunction *f = funcs.at(fi);
1682 if (f->isRemovedFromAllLanguages(f->implementingClass()))
1683 continue;
1684
1685 uint cmp = f->compareTo(sf);
1686
1687 if (cmp & AbstractMetaFunction::EqualModifiedName) {
1688 // printf(" - %s::%s similar to %s::%s %x vs %x\n",
1689 // qPrintable(sf->implementingClass()->typeEntry()->qualifiedCppName()),
1690 // qPrintable(sf->name()),
1691 // qPrintable(f->implementingClass()->typeEntry()->qualifiedCppName()),
1692 // qPrintable(f->name()),
1693 // sf->attributes(),
1694 // f->attributes());
1695
1696 add = false;
1697 if (cmp & AbstractMetaFunction::EqualArguments) {
1698
1699 // if (!(cmp & AbstractMetaFunction::EqualReturnType)) {
1700 // ReportHandler::warning(QString("%1::%2 and %3::%4 differ in retur type")
1701 // .arg(sf->implementingClass()->name())
1702 // .arg(sf->name())
1703 // .arg(f->implementingClass()->name())
1704 // .arg(f->name()));
1705 // }
1706
1707 // Same function, propegate virtual...
1708 if (!(cmp & AbstractMetaFunction::EqualAttributes)) {
1709 if (!f->isEmptyFunction()) {
1710 if (!sf->isFinalInCpp() && f->isFinalInCpp()) {
1711 *f -= AbstractMetaAttributes::FinalInCpp;
1712 // printf(" --- inherit virtual\n");
1713 }
1714 if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) {
1715 *f -= AbstractMetaAttributes::FinalInTargetLang;
1716 // printf(" --- inherit virtual\n");
1717 }
1718 if (!f->isFinalInTargetLang() && f->isPrivate()) {
1719 f->setFunctionType(AbstractMetaFunction::EmptyFunction);
1720 f->setVisibility(AbstractMetaAttributes::Protected);
1721 *f += AbstractMetaAttributes::FinalInTargetLang;
1722 ReportHandler::warning(QString("private virtual function '%1' in '%2'")
1723 .arg(f->signature())
1724 .arg(f->implementingClass()->name()));
1725 }
1726 }
1727 }
1728
1729 if (f->visibility() != sf->visibility()) {
1730 QString warn = QString("visibility of function '%1' modified in class '%2'")
1731 .arg(f->name()).arg(name());
1732 ReportHandler::warning(warn);
1733
1734 // If new visibility is private, we can't
1735 // do anything. If it isn't, then we
1736 // prefer the parent class's visibility
1737 // setting for the function.
1738 if (!f->isPrivate() && !sf->isPrivate())
1739 f->setVisibility(sf->visibility());
1740
1741 // Private overrides of abstract functions have to go into the class or
1742 // the subclasses will not compile as non-abstract classes.
1743 // But they don't need to be implemented, since they can never be called.
1744 if (f->isPrivate() && sf->isAbstract()) {
1745 f->setFunctionType(AbstractMetaFunction::EmptyFunction);
1746 f->setVisibility(sf->visibility());
1747 *f += AbstractMetaAttributes::FinalInTargetLang;
1748 *f += AbstractMetaAttributes::FinalInCpp;
1749 }
1750 }
1751
1752 // Set the class which first declares this function, afawk
1753 f->setDeclaringClass(sf->declaringClass());
1754
1755 if (sf->isFinalInTargetLang() && !sf->isPrivate() && !f->isPrivate() && !sf->isStatic() && !f->isStatic()) {
1756 // Shadowed funcion, need to make base class
1757 // function non-virtual
1758 if (f->implementingClass() != sf->implementingClass() && f->implementingClass()->inheritsFrom(sf->implementingClass())) {
1759
1760 // Check whether the superclass method has been redefined to non-final
1761
1762 bool hasNonFinalModifier = false;
1763 bool isBaseImplPrivate = false;
1764 FunctionModificationList mods = sf->modifications(sf->implementingClass());
1765 foreach (FunctionModification mod, mods) {
1766 if (mod.isNonFinal()) {
1767 hasNonFinalModifier = true;
1768 break;
1769 } else if (mod.isPrivate()) {
1770 isBaseImplPrivate = true;
1771 break;
1772 }
1773 }
1774
1775 if (!hasNonFinalModifier && !isBaseImplPrivate) {
1776 ReportHandler::warning(QString::fromLatin1("Shadowing: %1::%2 and %3::%4; Java code will not compile")
1777 .arg(sf->implementingClass()->name())
1778 .arg(sf->signature())
1779 .arg(f->implementingClass()->name())
1780 .arg(f->signature()));
1781 }
1782 }
1783 }
1784
1785 }
1786
1787 if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) {
1788 AbstractMetaArgumentList arguments;
1789 if (f->arguments().size() < sf->arguments().size())
1790 arguments = sf->arguments();
1791 else
1792 arguments = f->arguments();
1793 /* qtd
1794 for (int i=0; i<arguments.size(); ++i)
1795 arguments[i]->setDefaultValueExpression(QString());
1796 */ }
1797
1798
1799 // Otherwise we have function shadowing and we can
1800 // skip the thing...
1801 } else if (cmp & AbstractMetaFunction::EqualName && !sf->isSignal()) {
1802
1803 // In the case of function shadowing where the function name has been altered to
1804 // avoid conflict, we don't copy in the original.
1805 add = false;
1806 }
1807
1808 }
1809
1810 if (add)
1811 funcs_to_add << sf;
1812 }
1813
1814 foreach (AbstractMetaFunction *f, funcs_to_add)
1815 funcs << f->copy();
1816
1817 if (super_class)
1818 super_class = super_class->baseClass();
1819 else
1820 iface_idx++;
1821 }
1822
1823 bool hasPrivateConstructors = false;
1824 bool hasPublicConstructors = false;
1825 foreach (AbstractMetaFunction *func, funcs) {
1826 FunctionModificationList mods = func->modifications(this);
1827 foreach (const FunctionModification &mod, mods) {
1828 if (mod.isRenameModifier()) {
1829 // qDebug() << name() << func->originalName() << func << " from "
1830 // << func->implementingClass()->name() << "renamed to" << mod.renamedTo();
1831 func->setName(mod.renamedTo());
1832 }
1833 }
1834
1835 // Make sure class is abstract if one of the functions is
1836 if (func->isAbstract()) {
1837 (*this) += AbstractMetaAttributes::Abstract;
1838 (*this) -= AbstractMetaAttributes::Final;
1839 }
1840
1841 if (func->isConstructor()) {
1842 if (func->isPrivate())
1843 hasPrivateConstructors = true;
1844 else
1845 hasPublicConstructors = true;
1846 }
1847
1848
1849
1850 // Make sure that we include files for all classes that are in use
1851
1852 if (!func->isRemovedFrom(this, TypeSystem::ShellCode))
1853 add_extra_includes_for_function(this, func);
1854 }
1855
1856 if (hasPrivateConstructors && !hasPublicConstructors) {
1857 (*this) += AbstractMetaAttributes::Abstract;
1858 (*this) -= AbstractMetaAttributes::Final;
1859 }
1860
1861 foreach (AbstractMetaFunction *f1, funcs) {
1862 foreach (AbstractMetaFunction *f2, funcs) {
1863 if (f1 != f2) {
1864 uint cmp = f1->compareTo(f2);
1865 if ((cmp & AbstractMetaFunction::EqualName)
1866 && !f1->isFinalInCpp()
1867 && f2->isFinalInCpp()) {
1868 *f2 += AbstractMetaAttributes::FinalOverload;
1869 // qDebug() << f2 << f2->implementingClass()->name() << "::" << f2->name() << f2->arguments().size() << " vs " << f1 << f1->implementingClass()->name() << "::" << f1->name() << f1->arguments().size();
1870 // qDebug() << " " << f2;
1871 // AbstractMetaArgumentList f2Args = f2->arguments();
1872 // foreach (AbstractMetaArgument *a, f2Args)
1873 // qDebug() << " " << a->type()->name() << a->name();
1874 // qDebug() << " " << f1;
1875 // AbstractMetaArgumentList f1Args = f1->arguments();
1876 // foreach (AbstractMetaArgument *a, f1Args)
1877 // qDebug() << " " << a->type()->name() << a->name();
1878
1879 }
1880 }
1881 }
1882 }
1883
1884 setFunctions(funcs);
1885 }
1886
1887
1888 QString AbstractMetaType::minimalSignature() const
1889 {
1890 QString minimalSignature;
1891 if (isConstant())
1892 minimalSignature += "const ";
1893 minimalSignature += typeEntry()->qualifiedCppName();
1894 if (hasInstantiations()) {
1895 QList<AbstractMetaType *> instantiations = this->instantiations();
1896 minimalSignature += "<";
1897 for (int i=0;i<instantiations.size();++i) {
1898 if (i > 0)
1899 minimalSignature += ",";
1900 minimalSignature += instantiations.at(i)->minimalSignature();
1901 }
1902 minimalSignature += ">";
1903 }
1904
1905 if (isReference())
1906 minimalSignature += "&";
1907 for (int j=0; j<indirections(); ++j)
1908 minimalSignature += "*";
1909
1910 return minimalSignature;
1911 }
1912
1913 bool AbstractMetaType::hasNativeId() const
1914 {
1915 return (isQObject() || isValue() || isObject()) && typeEntry()->isNativeIdBased();
1916 }
1917
1918
1919 /*******************************************************************************
1920 * Other stuff...
1921 */
1922
1923
1924 AbstractMetaEnum *AbstractMetaClassList::findEnum(const EnumTypeEntry *entry) const
1925 {
1926 Q_ASSERT(entry->isEnum());
1927
1928 QString qualified_name = entry->qualifiedCppName();
1929 int pos = qualified_name.lastIndexOf("::");
1930
1931 QString enum_name;
1932 QString class_name;
1933
1934 if (pos > 0) {
1935 enum_name = qualified_name.mid(pos + 2);
1936 class_name = qualified_name.mid(0, pos);
1937 } else {
1938 enum_name = qualified_name;
1939 class_name = TypeDatabase::globalNamespaceClassName(entry);
1940 }
1941
1942 AbstractMetaClass *meta_class = findClass(class_name);
1943 if (!meta_class) {
1944 ReportHandler::warning(QString("AbstractMeta::findEnum(), unknown class '%1' in '%2'")
1945 .arg(class_name).arg(entry->qualifiedCppName()));
1946 return 0;
1947 }
1948
1949 return meta_class->findEnum(enum_name);
1950 }
1951
1952 AbstractMetaEnumValue *AbstractMetaEnumValueList::find(const QString &name) const
1953 {
1954 for (int i=0; i<size(); ++i) {
1955 if (name == at(i)->name())
1956 return at(i);
1957 }
1958 return 0;
1959 }
1960
1961 AbstractMetaEnumValue *AbstractMetaClassList::findEnumValue(const QString &name) const
1962 {
1963 QStringList lst = name.split(QLatin1String("::"));
1964
1965 Q_ASSERT_X(lst.size() == 2, "AbstractMetaClassList::findEnumValue()", "Expected qualified enum");
1966
1967
1968 QString prefixName = lst.at(0);
1969 QString enumName = lst.at(1);
1970
1971 AbstractMetaClass *cl = findClass(prefixName);
1972 if (cl)
1973 return cl->findEnumValue(enumName, 0);
1974
1975 ReportHandler::warning(QString("no matching enum '%1'").arg(name));
1976 return 0;
1977 }
1978
1979 /*!
1980 * Searches the list after a class that mathces \a name; either as
1981 * C++, Java base name or complete Java package.class name.
1982 */
1983
1984 AbstractMetaClass *AbstractMetaClassList::findClass(const QString &name) const
1985 {
1986 if (name.isEmpty())
1987 return 0;
1988
1989 foreach (AbstractMetaClass *c, *this) {
1990 if (c->qualifiedCppName() == name)
1991 return c;
1992 }
1993
1994 foreach (AbstractMetaClass *c, *this) {
1995 if (c->fullName() == name)
1996 return c;
1997 }
1998
1999 foreach (AbstractMetaClass *c, *this) {
2000 if (c->name() == name)
2001 return c;
2002 }
2003
2004 return 0;
2005 }
2006
2007 ArgumentReplace *ArgumentReplace::m_instance = 0;
2008
2009 ArgumentReplace::ArgumentReplace()
2010 {
2011 }
2012
2013 void ArgumentReplace::init()
2014 {
2015 if (m_instance)
2016 return;
2017
2018 m_instance = new ArgumentReplace();
2019 m_instance->data["version"] = "_version";
2020 m_instance->data["parent"] = "_parent";
2021 m_instance->data["delegate"] = "_delegate";
2022 m_instance->data["align"] = "_align";
2023 m_instance->data["in"] = "_in";
2024 m_instance->data["out"] = "_out";
2025 m_instance->data["scope"] = "_scope";
2026 m_instance->data["default"] = "_default";
2027 }
2028
2029 QString ArgumentReplace::translate(QString arg)
2030 {
2031 if (m_instance->data.contains(arg))
2032 return m_instance->data[arg];
2033 else
2034 return arg;
2035 }