1
/*
2
 * This file is part of the API Extractor project.
3
 *
4
 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
5
 *
6
 * Contact: PySide team <contact@pyside.org>
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * version 2 as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20
 * 02110-1301 USA
21
 *
22
 */
23
24
#include "abstractmetabuilder.h"
25
#include "reporthandler.h"
26
#include "typedatabase.h"
27
28
#include "parser/ast.h"
29
#include "parser/binder.h"
30
#include "parser/control.h"
31
#include "parser/default_visitor.h"
32
#include "parser/dumptree.h"
33
#include "parser/lexer.h"
34
#include "parser/parser.h"
35
#include "parser/tokens.h"
36
37
#include <QDebug>
38
#include <QFile>
39
#include <QFileInfo>
40
#include <QTextCodec>
41
#include <QTextStream>
42
#include <QVariant>
43
#include <QTime>
44
#include <QQueue>
45
#include <QDir>
46
47
#include <cstdio>
48
#include <algorithm>
49
#include "graph.h"
50
#include <QTemporaryFile>
51
52
static QString stripTemplateArgs(const QString &name)
53
{
54
    int pos = name.indexOf('<');
55
    return pos < 0 ? name : name.left(pos);
56
}
57
58
AbstractMetaBuilder::AbstractMetaBuilder() : m_currentClass(0), m_logDirectory(QString('.')+QDir::separator())
59
{
60
}
61
62
AbstractMetaBuilder::~AbstractMetaBuilder()
63
{
64
    qDeleteAll(m_globalEnums);
65
    qDeleteAll(m_globalFunctions);
66
    qDeleteAll(m_templates);
67
    qDeleteAll(m_metaClasses);
68
}
69
70
void AbstractMetaBuilder::checkFunctionModifications()
71
{
72
    TypeDatabase *types = TypeDatabase::instance();
73
    SingleTypeEntryHash entryHash = types->entries();
74
    QList<TypeEntry*> entries = entryHash.values();
75
76
    foreach (TypeEntry* entry, entries) {
77
        if (!entry)
78
            continue;
79
        if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
80
            continue;
81
82
        ComplexTypeEntry* centry = static_cast<ComplexTypeEntry*>(entry);
83
        FunctionModificationList modifications = centry->functionModifications();
84
85
        foreach (FunctionModification modification, modifications) {
86
            QString signature = modification.signature;
87
88
            QString name = signature.trimmed();
89
            name = name.mid(0, signature.indexOf("("));
90
91
            AbstractMetaClass* clazz = m_metaClasses.findClass(centry->qualifiedCppName());
92
            if (!clazz)
93
                continue;
94
95
            AbstractMetaFunctionList functions = clazz->functions();
96
            bool found = false;
97
            QStringList possibleSignatures;
98
            foreach (AbstractMetaFunction *function, functions) {
99
                if (function->minimalSignature() == signature && function->implementingClass() == clazz) {
100
                    found = true;
101
                    break;
102
                }
103
104
                if (function->originalName() == name)
105
                    possibleSignatures.append(function->minimalSignature() + " in " + function->implementingClass()->name());
106
            }
107
108
            if (!found) {
109
                QString warning
110
                = QString("signature '%1' for function modification in '%2' not found. Possible candidates: %3")
111
                  .arg(signature)
112
                  .arg(clazz->qualifiedCppName())
113
                  .arg(possibleSignatures.join(", "));
114
115
                ReportHandler::warning(warning);
116
            }
117
        }
118
    }
119
}
120
121
AbstractMetaClass* AbstractMetaBuilder::argumentToClass(ArgumentModelItem argument)
122
{
123
    AbstractMetaClass* returned = 0;
124
    bool ok = false;
125
    AbstractMetaType* type = translateType(argument->type(), &ok);
126
    if (ok && type && type->typeEntry() && type->typeEntry()->isComplex()) {
127
        const TypeEntry *entry = type->typeEntry();
128
        returned = m_metaClasses.findClass(entry->name());
129
    }
130
    delete type;
131
    return returned;
132
}
133
134
/**
135
 * Checks the argument of a hash function and flags the type if it is a complex type
136
 */
137
void AbstractMetaBuilder::registerHashFunction(FunctionModelItem function_item)
138
{
139
    ArgumentList arguments = function_item->arguments();
140
    if (arguments.size() == 1) {
141
        if (AbstractMetaClass *cls = argumentToClass(arguments.at(0)))
142
            cls->setHasHashFunction(true);
143
    }
144
}
145
146
/**
147
 * Check if a class has a debug stream operator that can be used as toString
148
 */
149
150
void AbstractMetaBuilder::registerToStringCapability(FunctionModelItem function_item)
151
{
152
    ArgumentList arguments = function_item->arguments();
153
    if (arguments.size() == 2) {
154
        if (arguments.at(0)->type().toString() == "QDebug") {
155
            ArgumentModelItem arg = arguments.at(1);
156
            if (AbstractMetaClass *cls = argumentToClass(arg)) {
157
                if (arg->type().indirections() < 2)
158
                    cls->setToStringCapability(true);
159
            }
160
        }
161
    }
162
}
163
164
void AbstractMetaBuilder::traverseOperatorFunction(FunctionModelItem item)
165
{
166
    if (item->accessPolicy() != CodeModel::Public)
167
        return;
168
169
    ArgumentList arguments = item->arguments();
170
    AbstractMetaClass* baseoperandClass;
171
    bool firstArgumentIsSelf = true;
172
    bool unaryOperator = false;
173
174
    baseoperandClass = argumentToClass(arguments.at(0));
175
176
    if (arguments.size() == 1) {
177
        unaryOperator = true;
178
    } else if (!baseoperandClass
179
               || !(baseoperandClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) {
180
        baseoperandClass = argumentToClass(arguments.at(1));
181
        firstArgumentIsSelf = false;
182
    } else {
183
        bool ok;
184
        AbstractMetaType* type = translateType(item->type(), &ok);
185
        const TypeEntry* retType = ok ? type->typeEntry() : 0;
186
        AbstractMetaClass* otherArgClass = argumentToClass(arguments.at(1));
187
        if (otherArgClass && retType
188
            && (retType->isValue() || retType->isObject())
189
            && retType != baseoperandClass->typeEntry()
190
            && retType == otherArgClass->typeEntry()) {
191
            baseoperandClass = m_metaClasses.findClass(retType);
192
            firstArgumentIsSelf = false;
193
        }
194
        delete type;
195
    }
196
197
    if (baseoperandClass) {
198
        AbstractMetaClass* oldCurrentClass = m_currentClass;
199
        m_currentClass = baseoperandClass;
200
        AbstractMetaFunction *metaFunction = traverseFunction(item);
201
        if (metaFunction && !metaFunction->isInvalid()) {
202
            // Strip away first argument, since that is the containing object
203
            AbstractMetaArgumentList arguments = metaFunction->arguments();
204
            if (firstArgumentIsSelf || unaryOperator) {
205
                AbstractMetaArgument* first = arguments.takeFirst();
206
                if (!unaryOperator && first->type()->indirections())
207
                    metaFunction->setPointerOperator(true);
208
                delete first;
209
                metaFunction->setArguments(arguments);
210
            } else {
211
                // If the operator method is not unary and the first operator is
212
                // not of the same type of its owning class we suppose that it
213
                // must be an reverse operator (e.g. CLASS::operator(TYPE, CLASS)).
214
                // All operator overloads that operate over a class are already
215
                // being added as member functions of that class by the API Extractor.
216
                AbstractMetaArgument* last = arguments.takeLast();
217
                if (last->type()->indirections())
218
                    metaFunction->setPointerOperator(true);
219
                delete last;
220
221
                metaFunction->setArguments(arguments);
222
                metaFunction->setReverseOperator(true);
223
            }
224
            metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction);
225
            metaFunction->setVisibility(AbstractMetaFunction::Public);
226
            metaFunction->setOriginalAttributes(metaFunction->attributes());
227
            setupFunctionDefaults(metaFunction, baseoperandClass);
228
            baseoperandClass->addFunction(metaFunction);
229
            Q_ASSERT(!metaFunction->wasPrivate());
230
        } else if (metaFunction) {
231
            delete metaFunction;
232
        }
233
234
        m_currentClass = oldCurrentClass;
235
    }
236
}
237
238
void AbstractMetaBuilder::traverseStreamOperator(FunctionModelItem item)
239
{
240
    ArgumentList arguments = item->arguments();
241
    if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
242
        AbstractMetaClass* streamClass = argumentToClass(arguments.at(0));
243
        AbstractMetaClass* streamedClass = argumentToClass(arguments.at(1));
244
245
        if (streamClass && streamedClass && (streamClass->isStream())) {
246
            AbstractMetaClass *oldCurrentClass = m_currentClass;
247
            m_currentClass = streamedClass;
248
            AbstractMetaFunction *streamFunction = traverseFunction(item);
249
250
            if (streamFunction && !streamFunction->isInvalid()) {
251
                QString name = item->name();
252
                streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
253
                // Strip first argument, since that is the containing object
254
                AbstractMetaArgumentList arguments = streamFunction->arguments();
255
                if (!streamClass->typeEntry()->generateCode())
256
                    delete arguments.takeLast();
257
                else
258
                    delete arguments.takeFirst();
259
260
                streamFunction->setArguments(arguments);
261
262
                *streamFunction += AbstractMetaAttributes::Final;
263
                *streamFunction += AbstractMetaAttributes::Public;
264
                streamFunction->setOriginalAttributes(streamFunction->attributes());
265
266
//              streamFunction->setType(0);
267
268
                AbstractMetaClass *funcClass;
269
270
                if (!streamClass->typeEntry()->generateCode()) {
271
                    AbstractMetaArgumentList reverseArgs = reverseList(streamFunction->arguments());
272
                    streamFunction->setArguments(reverseArgs);
273
                    streamFunction->setReverseOperator(true);
274
                    funcClass = streamedClass;
275
                } else {
276
                    funcClass = streamClass;
277
                }
278
279
                setupFunctionDefaults(streamFunction, funcClass);
280
                funcClass->addFunction(streamFunction);
281
                if (funcClass == streamClass)
282
                    funcClass->typeEntry()->addExtraInclude(streamedClass->typeEntry()->include());
283
                else
284
                    funcClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
285
286
                m_currentClass = oldCurrentClass;
287
            } else if (streamFunction) {
288
                delete streamFunction;
289
            }
290
291
        }
292
    }
293
}
294
295
void AbstractMetaBuilder::fixQObjectForScope(TypeDatabase *types,
296
                                             NamespaceModelItem scope)
297
{
298
    foreach (ClassModelItem item, scope->classes()) {
299
        QString qualifiedName = item->qualifiedName().join("::");
300
        TypeEntry* entry = types->findType(qualifiedName);
301
        if (entry) {
302
            if (isQObject(qualifiedName) && entry->isComplex())
303
                ((ComplexTypeEntry*) entry)->setQObject(true);
304
        }
305
    }
306
307
    foreach (NamespaceModelItem item, scope->namespaceMap().values()) {
308
        if (scope != item)
309
            fixQObjectForScope(types, item);
310
    }
311
}
312
313
void AbstractMetaBuilder::sortLists()
314
{
315
    foreach (AbstractMetaClass *cls, m_metaClasses)
316
        cls->sortFunctions();
317
}
318
319
bool AbstractMetaBuilder::build(QIODevice* input)
320
{
321
    Q_ASSERT(input);
322
323
    if (!input->isOpen()) {
324
        if (!input->open(QIODevice::ReadOnly))
325
            return false;
326
    }
327
328
    TypeDatabase* types = TypeDatabase::instance();
329
330
    QByteArray contents = input->readAll();
331
    input->close();
332
333
    Control control;
334
    Parser p(&control);
335
    pool __pool;
336
337
    TranslationUnitAST* ast = p.parse(contents, contents.size(), &__pool);
338
339
    CodeModel model;
340
    Binder binder(&model, p.location());
341
    m_dom = binder.run(ast);
342
343
    pushScope(model_dynamic_cast<ScopeModelItem>(m_dom));
344
345
    QHash<QString, ClassModelItem> typeMap = m_dom->classMap();
346
347
    // fix up QObject's in the type system..
348
    fixQObjectForScope(types, model_dynamic_cast<NamespaceModelItem>(m_dom));
349
350
    // Start the generation...
351
    ClassList typeValues = typeMap.values();
352
    qSort(typeValues);
353
    ClassList::iterator it = std::unique(typeValues.begin(), typeValues.end());
354
    typeValues.erase(it, typeValues.end());
355
356
    ReportHandler::setProgressReference(typeValues);
357
    foreach (ClassModelItem item, typeValues) {
358
        ReportHandler::progress("Generating class model...");
359
        AbstractMetaClass *cls = traverseClass(item);
360
        if (!cls)
361
            continue;
362
363
        addAbstractMetaClass(cls);
364
    }
365
    ReportHandler::flush();
366
367
    // We need to know all global enums
368
    QHash<QString, EnumModelItem> enumMap = m_dom->enumMap();
369
    ReportHandler::setProgressReference(enumMap);
370
    foreach (EnumModelItem item, enumMap) {
371
        ReportHandler::progress("Generating enum model...");
372
        AbstractMetaEnum *metaEnum = traverseEnum(item, 0, QSet<QString>());
373
        if (metaEnum) {
374
            if (metaEnum->typeEntry()->generateCode())
375
                m_globalEnums << metaEnum;
376
        }
377
    }
378
    ReportHandler::flush();
379
380
    QHash<QString, NamespaceModelItem> namespaceMap = m_dom->namespaceMap();
381
    NamespaceList namespaceTypeValues = namespaceMap.values();
382
    qSort(namespaceTypeValues);
383
    NamespaceList::iterator nsit = std::unique(namespaceTypeValues.begin(), namespaceTypeValues.end());
384
    namespaceTypeValues.erase(nsit, namespaceTypeValues.end());
385
386
    ReportHandler::setProgressReference(namespaceMap);
387
    foreach (NamespaceModelItem item, namespaceTypeValues) {
388
        ReportHandler::progress("Generating namespace model...");
389
        AbstractMetaClass *metaClass = traverseNamespace(item);
390
        if (metaClass)
391
            m_metaClasses << metaClass;
392
    }
393
    ReportHandler::flush();
394
395
    // Go through all typedefs to see if we have defined any
396
    // specific typedefs to be used as classes.
397
    TypeAliasList typeAliases = m_dom->typeAliases();
398
    ReportHandler::setProgressReference(typeAliases);
399
    foreach (TypeAliasModelItem typeAlias, typeAliases) {
400
        ReportHandler::progress("Resolving typedefs...");
401
        AbstractMetaClass* cls = traverseTypeAlias(typeAlias);
402
        addAbstractMetaClass(cls);
403
    }
404
    ReportHandler::flush();
405
406
    figureOutEnumValues();
407
408
    foreach (ClassModelItem item, typeValues)
409
        traverseClassMembers(item);
410
411
    foreach (NamespaceModelItem item, namespaceTypeValues)
412
        traverseNamespaceMembers(item);
413
414
    // Global functions
415
    foreach (FunctionModelItem func, m_dom->functions()) {
416
        if (func->accessPolicy() != CodeModel::Public || func->name().startsWith("operator"))
417
            continue;
418
419
        FunctionTypeEntry* funcEntry = types->findFunctionType(func->name());
420
        if (!funcEntry || !funcEntry->generateCode())
421
            continue;
422
423
        AbstractMetaFunction* metaFunc = traverseFunction(func);
424
        if (!metaFunc)
425
            continue;
426
427
        if (!funcEntry->hasSignature(metaFunc->minimalSignature())) {
428
            delete metaFunc;
429
            continue;
430
        }
431
432
        applyFunctionModifications(metaFunc);
433
434
        setInclude(funcEntry, func->fileName());
435
        if (metaFunc->typeEntry())
436
            delete metaFunc->typeEntry();
437
438
        metaFunc->setTypeEntry(funcEntry);
439
        m_globalFunctions << metaFunc;
440
    }
441
442
    ReportHandler::setProgressReference(m_metaClasses);
443
    foreach (AbstractMetaClass* cls, m_metaClasses) {
444
        ReportHandler::progress("Fixing class inheritance...");
445
        if (!cls->isInterface() && !cls->isNamespace())
446
            setupInheritance(cls);
447
    }
448
    ReportHandler::flush();
449
450
    ReportHandler::setProgressReference(m_metaClasses);
451
    foreach (AbstractMetaClass* cls, m_metaClasses) {
452
        ReportHandler::progress("Detecting inconsistencies in class model...");
453
        cls->fixFunctions();
454
455
        if (!cls->typeEntry()) {
456
            ReportHandler::warning(QString("class '%1' does not have an entry in the type system")
457
                                   .arg(cls->name()));
458
        } else {
459
            bool couldAddDefaultCtors = !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace();
460
            if (couldAddDefaultCtors) {
461
                if (!cls->hasConstructors())
462
                    cls->addDefaultConstructor();
463
                if (cls->typeEntry()->isValue() && !cls->isAbstract() && !cls->hasCopyConstructor())
464
                    cls->addDefaultCopyConstructor(ancestorHasPrivateCopyConstructor(cls));
465
            }
466
        }
467
468
        if (cls->isAbstract() && !cls->isInterface())
469
            cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + "$ConcreteWrapper");
470
    }
471
    ReportHandler::flush();
472
473
    TypeEntryHash allEntries = types->allEntries();
474
    ReportHandler::progress("Detecting inconsistencies in typesystem...");
475
    foreach (QList<TypeEntry*> entries, allEntries) {
476
        foreach (TypeEntry* entry, entries) {
477
478
            if (entry->isPrimitive())
479
                continue;
480
481
            if ((entry->isValue() || entry->isObject())
482
                && !entry->isString()
483
                && !entry->isChar()
484
                && !entry->isContainer()
485
                && !entry->isCustom()
486
                && !entry->isVariant()
487
                && !m_metaClasses.findClass(entry->qualifiedCppName())) {
488
                ReportHandler::warning(QString("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
489
                                    .arg(entry->qualifiedCppName()));
490
            } else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) {
491
                const FunctionTypeEntry* fte = static_cast<const FunctionTypeEntry*>(entry);
492
                foreach (QString signature, fte->signatures()) {
493
                    bool ok = false;
494
                    foreach (AbstractMetaFunction* func, m_globalFunctions) {
495
                        if (signature == func->minimalSignature()) {
496
                            ok = true;
497
                            break;
498
                        }
499
                    }
500
                    if (!ok) {
501
                        ReportHandler::warning(QString("Global function '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
502
                        .arg(signature));
503
                    }
504
                }
505
            } else if (entry->isEnum()) {
506
                const QString name = ((EnumTypeEntry*) entry)->targetLangQualifier();
507
                AbstractMetaClass* cls = m_metaClasses.findClass(name);
508
509
                bool enumFound = false;
510
                if (cls) {
511
                    enumFound = cls->findEnum(entry->targetLangName());
512
                } else { // Global enum
513
                    foreach (AbstractMetaEnum* metaEnum, m_enums) {
514
                        if (metaEnum->typeEntry() == entry) {
515
                            enumFound = true;
516
                            break;
517
                        }
518
                    }
519
                }
520
                if (!enumFound) {
521
                    entry->setCodeGeneration(TypeEntry::GenerateNothing);
522
                    ReportHandler::warning(QString("enum '%1' is specified in typesystem, but not declared")
523
                                           .arg(entry->qualifiedCppName()));
524
                }
525
526
            }
527
        }
528
    }
529
    ReportHandler::flush();
530
531
    {
532
        FunctionList hashFunctions = m_dom->findFunctions("qHash");
533
        foreach (FunctionModelItem item, hashFunctions)
534
            registerHashFunction(item);
535
    }
536
537
    {
538
        FunctionList hashFunctions = m_dom->findFunctions("operator<<");
539
        foreach (FunctionModelItem item, hashFunctions)
540
            registerToStringCapability(item);
541
    }
542
543
    {
544
        FunctionList binaryOperators = m_dom->findFunctions("operator==")
545
                                        + m_dom->findFunctions("operator!=")
546
                                        + m_dom->findFunctions("operator<=")
547
                                        + m_dom->findFunctions("operator>=")
548
                                        + m_dom->findFunctions("operator<")
549
                                        + m_dom->findFunctions("operator+")
550
                                        + m_dom->findFunctions("operator/")
551
                                        + m_dom->findFunctions("operator*")
552
                                        + m_dom->findFunctions("operator-")
553
                                        + m_dom->findFunctions("operator&")
554
                                        + m_dom->findFunctions("operator|")
555
                                        + m_dom->findFunctions("operator^")
556
                                        + m_dom->findFunctions("operator~")
557
                                        + m_dom->findFunctions("operator>");
558
559
        foreach (FunctionModelItem item, binaryOperators)
560
            traverseOperatorFunction(item);
561
    }
562
563
    {
564
        FunctionList streamOperators = m_dom->findFunctions("operator<<") + m_dom->findFunctions("operator>>");
565
        foreach (FunctionModelItem item, streamOperators)
566
            traverseStreamOperator(item);
567
    }
568
569
    figureOutDefaultEnumArguments();
570
    checkFunctionModifications();
571
572
    // sort all classes topologically
573
    m_metaClasses = classesTopologicalSorted();
574
575
    foreach (AbstractMetaClass* cls, m_metaClasses) {
576
//         setupEquals(cls);
577
//         setupComparable(cls);
578
        setupClonable(cls);
579
        setupExternalConversion(cls);
580
581
        // sort all inner classes topologically
582
        if (!cls->typeEntry()->codeGeneration() || cls->innerClasses().size() < 2)
583
            continue;
584
585
        cls->setInnerClasses(classesTopologicalSorted(cls));
586
    }
587
588
    dumpLog();
589
590
    sortLists();
591
592
    m_currentClass = 0;
593
594
    // Functions added to the module on the type system.
595
    foreach (AddedFunction addedFunc, types->globalUserFunctions()) {
596
        AbstractMetaFunction* metaFunc = traverseFunction(addedFunc);
597
        metaFunc->setFunctionType(AbstractMetaFunction::NormalFunction);
598
        m_globalFunctions << metaFunc;
599
    }
600
601
    std::puts("");
602
    return true;
603
}
604
605
void AbstractMetaBuilder::setLogDirectory(const QString& logDir)
606
{
607
    m_logDirectory = logDir;
608
    if (!m_logDirectory.endsWith(QDir::separator()))
609
       m_logDirectory.append(QDir::separator());
610
}
611
612
void AbstractMetaBuilder::addAbstractMetaClass(AbstractMetaClass *cls)
613
{
614
    if (!cls)
615
        return;
616
617
    cls->setOriginalAttributes(cls->attributes());
618
    if (cls->typeEntry()->isContainer()) {
619
        m_templates << cls;
620
    } else {
621
        m_metaClasses << cls;
622
        if (cls->typeEntry()->designatedInterface()) {
623
            AbstractMetaClass* interface = cls->extractInterface();
624
            m_metaClasses << interface;
625
            ReportHandler::debugSparse(QString(" -> interface '%1'").arg(interface->name()));
626
        }
627
    }
628
}
629
630
AbstractMetaClass* AbstractMetaBuilder::traverseNamespace(NamespaceModelItem namespaceItem)
631
{
632
    QString namespaceName = (!m_namespacePrefix.isEmpty() ? m_namespacePrefix + "::" : QString()) + namespaceItem->name();
633
    NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespaceName);
634
635
    if (TypeDatabase::instance()->isClassRejected(namespaceName)) {
636
        m_rejectedClasses.insert(namespaceName, GenerationDisabled);
637
        return 0;
638
    }
639
640
    if (!type) {
641
        ReportHandler::warning(QString("namespace '%1' does not have a type entry").arg(namespaceName));
642
        return 0;
643
    }
644
645
    AbstractMetaClass* metaClass = createMetaClass();
646
    metaClass->setTypeEntry(type);
647
648
    *metaClass += AbstractMetaAttributes::Public;
649
650
    m_currentClass = metaClass;
651
652
    ReportHandler::debugSparse(QString("namespace '%1.%2'")
653
                               .arg(metaClass->package())
654
                               .arg(namespaceItem->name()));
655
656
    traverseEnums(model_dynamic_cast<ScopeModelItem>(namespaceItem), metaClass, namespaceItem->enumsDeclarations());
657
658
    pushScope(model_dynamic_cast<ScopeModelItem>(namespaceItem));
659
    m_namespacePrefix = currentScope()->qualifiedName().join("::");
660
661
    ClassList classes = namespaceItem->classes();
662
    foreach (ClassModelItem cls, classes) {
663
        AbstractMetaClass* mjc = traverseClass(cls);
664
        if (mjc) {
665
            metaClass->addInnerClass(mjc);
666
            mjc->setEnclosingClass(metaClass);
667
            addAbstractMetaClass(mjc);
668
        }
669
    }
670
671
    // Go through all typedefs to see if we have defined any
672
    // specific typedefs to be used as classes.
673
    TypeAliasList typeAliases = namespaceItem->typeAliases();
674
    foreach (TypeAliasModelItem typeAlias, typeAliases) {
675
        AbstractMetaClass* cls = traverseTypeAlias(typeAlias);
676
        if (cls) {
677
            metaClass->addInnerClass(cls);
678
            cls->setEnclosingClass(metaClass);
679
            addAbstractMetaClass(cls);
680
        }
681
    }
682
683
    // Traverse namespaces recursively
684
    NamespaceList innerNamespaces = namespaceItem->namespaceMap().values();
685
    qSort(innerNamespaces);
686
    NamespaceList::iterator it = std::unique(innerNamespaces.begin(), innerNamespaces.end());
687
    innerNamespaces.erase(it, innerNamespaces.end());
688
    foreach (const NamespaceModelItem &ni, innerNamespaces) {
689
        AbstractMetaClass* mjc = traverseNamespace(ni);
690
        if (mjc) {
691
            metaClass->addInnerClass(mjc);
692
            mjc->setEnclosingClass(metaClass);
693
            addAbstractMetaClass(mjc);
694
        }
695
    }
696
697
    m_currentClass = 0;
698
699
    popScope();
700
    m_namespacePrefix = currentScope()->qualifiedName().join("::");
701
702
    if (!type->include().isValid())
703
        setInclude(type, namespaceItem->fileName());
704
705
    return metaClass;
706
}
707
708
struct Operator
709
{
710
    enum Type { Complement, Plus, ShiftRight, ShiftLeft, None };
711
712
    Operator() : type(None) {}
713
714
    int calculate(int x)
715
    {
716
        switch (type) {
717
        case Complement: return ~value;
718
        case Plus: return x + value;
719
        case ShiftRight: return x >> value;
720
        case ShiftLeft: return x << value;
721
        case None: return x;
722
        }
723
        return x;
724
    }
725
726
    Type type;
727
    int value;
728
};
729
730
731
732
Operator findOperator(QString* s)
733
{
734
    const char *names[] = {
735
        "~",
736
        "+",
737
        ">>",
738
        "<<"
739
    };
740
741
    for (int i = 0; i < Operator::None; ++i) {
742
        QString name = QLatin1String(names[i]);
743
        QString str = *s;
744
        int splitPoint = str.indexOf(name);
745
        if (splitPoint > -1) {
746
            bool ok;
747
            QString right = str.mid(splitPoint + name.length());
748
            Operator op;
749
750
            op.value = right.toInt(&ok);
751
            if (!ok && right.length() > 0 && right.at(right.length() - 1).toLower() == QLatin1Char('u'))
752
                op.value = right.left(right.length() - 1).toUInt(&ok, 0);
753
754
            if (ok) {
755
                op.type = Operator::Type(i);
756
                if (splitPoint > 0)
757
                    *s = str.left(splitPoint).trimmed();
758
                else
759
                    *s = QString();
760
                return op;
761
            }
762
        }
763
    }
764
    return Operator();
765
}
766
767
int AbstractMetaBuilder::figureOutEnumValue(const QString &stringValue,
768
                                            int oldValuevalue,
769
                                            AbstractMetaEnum *metaEnum,
770
                                            AbstractMetaFunction *metaFunction)
771
{
772
    if (stringValue.isEmpty())
773
        return oldValuevalue;
774
775
    QStringList stringValues = stringValue.split("|");
776
777
    int returnValue = 0;
778
779
    bool matched = false;
780
781
    for (int i = 0; i < stringValues.size(); ++i) {
782
        QString s = stringValues.at(i).trimmed();
783
784
        bool ok;
785
        int v;
786
787
        Operator op = findOperator(&s);
788
789
        if (s.length() > 0 && s.at(0) == QLatin1Char('0'))
790
            v = s.toUInt(&ok, 0);
791
        else if (s.length() > 0 && s.at(s.length() - 1).toLower() == QLatin1Char('u'))
792
            v = s.left(s.length() - 1).toUInt(&ok, 0);
793
        else
794
            v = s.toInt(&ok);
795
796
        if (ok || s.isEmpty()) {
797
            matched = true;
798
        } else if (m_enumValues.contains(s)) {
799
            v = m_enumValues[s]->value();
800
            matched = true;
801
        } else {
802
            if (metaEnum) {
803
                v = findOutValueFromString(s, matched);
804
                if (!matched) {
805
                    QString enclosingClass = QString(metaEnum->enclosingClass() ? metaEnum->enclosingClass()->name() + "::" : QString());
806
                    ReportHandler::warning("unhandled enum value: " + s + " in "
807
                                           + enclosingClass + metaEnum->name()
808
                                           + " from header '" + metaEnum->typeEntry()->include().name() + "'");
809
                }
810
            } else {
811
                ReportHandler::warning("unhandled enum value: Unknown enum");
812
            }
813
        }
814
815
        if (matched)
816
            returnValue |= op.calculate(v);
817
    }
818
819
    if (!matched) {
820
        QString warn = QString("unmatched enum %1").arg(stringValue);
821
822
        if (metaFunction) {
823
            warn += QString(" when parsing default value of '%1' in class '%2'")
824
                    .arg(metaFunction->name())
825
                    .arg(metaFunction->implementingClass()->name());
826
        }
827
        warn += " from header '" + metaEnum->typeEntry()->include().name() + "'";
828
829
        ReportHandler::warning(warn);
830
        returnValue = oldValuevalue;
831
    }
832
833
    return returnValue;
834
}
835
836
void AbstractMetaBuilder::figureOutEnumValuesForClass(AbstractMetaClass* metaClass,
837
                                                      QSet<AbstractMetaClass*>* classes)
838
{
839
    AbstractMetaClass* base = metaClass->baseClass();
840
841
    if (base && !classes->contains(base))
842
        figureOutEnumValuesForClass(base, classes);
843
844
    if (classes->contains(metaClass))
845
        return;
846
847
    AbstractMetaEnumList enums = metaClass->enums();
848
    foreach (AbstractMetaEnum* e, enums) {
849
        if (!e) {
850
            ReportHandler::warning("bad enum in class " + metaClass->name());
851
            continue;
852
        }
853
        AbstractMetaEnumValueList lst = e->values();
854
        int value = 0;
855
        for (int i = 0; i < lst.size(); ++i) {
856
            value = figureOutEnumValue(lst.at(i)->stringValue(), value, e);
857
            lst.at(i)->setValue(value);
858
            value++;
859
        }
860
    }
861
862
    *classes += metaClass;
863
}
864
865
866
void AbstractMetaBuilder::figureOutEnumValues()
867
{
868
    // Keep a set of classes that we already traversed. We use this to
869
    // enforce that we traverse base classes prior to subclasses.
870
    QSet<AbstractMetaClass*> classes;
871
    foreach (AbstractMetaClass *c, m_metaClasses)
872
        figureOutEnumValuesForClass(c, &classes);
873
874
    foreach (AbstractMetaEnum* metaEnum, m_globalEnums) {
875
        AbstractMetaEnumValueList enumValues = metaEnum->values();
876
        int value = 0;
877
        for (int i = 0; i < enumValues.size(); ++i) {
878
            value = figureOutEnumValue(enumValues.at(i)->stringValue(), value, metaEnum);
879
            enumValues.at(i)->setValue(value);
880
            value++;
881
        }
882
    }
883
}
884
885
void AbstractMetaBuilder::figureOutDefaultEnumArguments()
886
{
887
    foreach (AbstractMetaClass* metaClass, m_metaClasses) {
888
        foreach (AbstractMetaFunction* metaFunction, metaClass->functions()) {
889
            foreach (AbstractMetaArgument *arg, metaFunction->arguments()) {
890
                QString expr = arg->defaultValueExpression();
891
                if (expr.isEmpty())
892
                    continue;
893
894
                if (!metaFunction->replacedDefaultExpression(metaFunction->implementingClass(),
895
                                                             arg->argumentIndex() + 1).isEmpty()) {
896
                    continue;
897
                }
898
899
                arg->setDefaultValueExpression(expr);
900
            }
901
        }
902
    }
903
}
904
905
906
AbstractMetaEnum* AbstractMetaBuilder::traverseEnum(EnumModelItem enumItem, AbstractMetaClass* enclosing, const QSet<QString> &enumsDeclarations)
907
{
908
    QString qualifiedName = enumItem->qualifiedName().join("::");
909
910
    TypeEntry* typeEntry = 0;
911
    if (enumItem->accessPolicy() == CodeModel::Private) {
912
        QStringList names = enumItem->qualifiedName();
913
        QString enumName = names.last();
914
        QString nspace;
915
        if (names.size() > 1)
916
            nspace = QStringList(names.mid(0, names.size() - 1)).join("::");
917
        typeEntry = new EnumTypeEntry(nspace, enumName, 0);
918
        TypeDatabase::instance()->addType(typeEntry);
919
    } else if (!enumItem->isAnonymous()) {
920
        typeEntry = TypeDatabase::instance()->findType(qualifiedName);
921
    } else {
922
        QStringList tmpQualifiedName = enumItem->qualifiedName();
923
        foreach (const EnumeratorModelItem& enumValue, enumItem->enumerators()) {
924
            tmpQualifiedName.removeLast();
925
            tmpQualifiedName << enumValue->name();
926
            qualifiedName = tmpQualifiedName.join("::");
927
            typeEntry = TypeDatabase::instance()->findType(qualifiedName);
928
            if (typeEntry)
929
                break;
930
        }
931
    }
932
933
    QString enumName = enumItem->name();
934
935
    QString className;
936
    if (m_currentClass)
937
        className = m_currentClass->typeEntry()->qualifiedCppName();
938
939
    if (TypeDatabase::instance()->isEnumRejected(className, enumName)) {
940
        if (typeEntry)
941
            typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
942
        m_rejectedEnums.insert(qualifiedName, GenerationDisabled);
943
        return 0;
944
    }
945
946
    if (!typeEntry || !typeEntry->isEnum()) {
947
        ReportHandler::warning(QString("enum '%1' does not have a type entry or is not an enum")
948
                               .arg(qualifiedName));
949
        m_rejectedEnums.insert(qualifiedName, NotInTypeSystem);
950
        return 0;
951
    }
952
953
    AbstractMetaEnum* metaEnum = createMetaEnum();
954
    if (enumsDeclarations.contains(qualifiedName)
955
        || enumsDeclarations.contains(enumName)) {
956
        metaEnum->setHasQEnumsDeclaration(true);
957
    }
958
959
    metaEnum->setTypeEntry((EnumTypeEntry*) typeEntry);
960
    switch (enumItem->accessPolicy()) {
961
    case CodeModel::Public:
962
        *metaEnum += AbstractMetaAttributes::Public;
963
        break;
964
    case CodeModel::Protected:
965
        *metaEnum += AbstractMetaAttributes::Protected;
966
        break;
967
    case CodeModel::Private:
968
        *metaEnum += AbstractMetaAttributes::Private;
969
        typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
970
        break;
971
    default:
972
        break;
973
    }
974
975
    ReportHandler::debugMedium(QString(" - traversing enum %1").arg(metaEnum->fullName()));
976
977
    foreach (EnumeratorModelItem value, enumItem->enumerators()) {
978
979
        AbstractMetaEnumValue* metaEnumValue = createMetaEnumValue();
980
        metaEnumValue->setName(value->name());
981
        // Deciding the enum value...
982
983
        metaEnumValue->setStringValue(value->value());
984
        metaEnum->addEnumValue(metaEnumValue);
985
986
        ReportHandler::debugFull("   - " + metaEnumValue->name() + " = "
987
                                 + metaEnumValue->value());
988
989
        // Add into global register...
990
        if (enclosing)
991
            m_enumValues[enclosing->name() + "::" + metaEnumValue->name()] = metaEnumValue;
992
        else
993
            m_enumValues[metaEnumValue->name()] = metaEnumValue;
994
    }
995
996
    m_enums << metaEnum;
997
998
    if (!metaEnum->typeEntry()->include().isValid())
999
        setInclude(metaEnum->typeEntry(), enumItem->fileName());
1000
1001
    metaEnum->setOriginalAttributes(metaEnum->attributes());
1002
1003
    // Register all enum values on Type database
1004
    foreach(EnumeratorModelItem e, enumItem->enumerators()) {
1005
        QString name;
1006
        if (enclosing) {
1007
            name += enclosing->name();
1008
            name += "::";
1009
        }
1010
        name += e->name();
1011
        EnumValueTypeEntry* enumValue = new EnumValueTypeEntry(name, e->value(), static_cast<EnumTypeEntry*>(typeEntry), typeEntry->version());
1012
        TypeDatabase::instance()->addType(enumValue);
1013
    }
1014
1015
    return metaEnum;
1016
}
1017
1018
AbstractMetaClass* AbstractMetaBuilder::traverseTypeAlias(TypeAliasModelItem typeAlias)
1019
{
1020
    TypeDatabase* types = TypeDatabase::instance();
1021
    QString className = stripTemplateArgs(typeAlias->name());
1022
1023
    QString fullClassName = className;
1024
    // we have an inner class
1025
    if (m_currentClass) {
1026
        fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName())
1027
                          + "::" + fullClassName;
1028
    }
1029
1030
    // If this is the alias for a primitive type
1031
    // we store the aliased type on the alias
1032
    // TypeEntry
1033
    PrimitiveTypeEntry* ptype = types->findPrimitiveType(className);
1034
    if (ptype) {
1035
        QString typeAliasName = typeAlias->type().qualifiedName()[0];
1036
        ptype->setAliasedTypeEntry(types->findPrimitiveType(typeAliasName));
1037
        return 0;
1038
    }
1039
1040
1041
    // If we haven't specified anything for the typedef, then we don't care
1042
    ComplexTypeEntry* type = types->findComplexType(fullClassName);
1043
    if (!type)
1044
        return 0;
1045
1046
    if (type->isObject())
1047
        static_cast<ObjectTypeEntry *>(type)->setQObject(isQObject(stripTemplateArgs(typeAlias->type().qualifiedName().join("::"))));
1048
1049
    AbstractMetaClass *metaClass = createMetaClass();
1050
    metaClass->setTypeAlias(true);
1051
    metaClass->setTypeEntry(type);
1052
    metaClass->setBaseClassNames(QStringList() << typeAlias->type().qualifiedName().join("::"));
1053
    *metaClass += AbstractMetaAttributes::Public;
1054
1055
    // Set the default include file name
1056
    if (!type->include().isValid())
1057
        setInclude(type, typeAlias->fileName());
1058
1059
    fillAddedFunctions(metaClass);
1060
1061
    return metaClass;
1062
}
1063
1064
AbstractMetaClass* AbstractMetaBuilder::traverseClass(ClassModelItem classItem)
1065
{
1066
    QString className = stripTemplateArgs(classItem->name());
1067
    QString fullClassName = className;
1068
1069
    // we have inner an class
1070
    if (m_currentClass) {
1071
        fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName())
1072
                          + "::" + fullClassName;
1073
    }
1074
1075
    ComplexTypeEntry* type = TypeDatabase::instance()->findComplexType(fullClassName);
1076
    RejectReason reason = NoReason;
1077
1078
    if (fullClassName == "QMetaTypeId") {
1079
        // QtScript: record which types have been declared
1080
        int lpos = classItem->name().indexOf('<');
1081
        int rpos = classItem->name().lastIndexOf('>');
1082
        if ((lpos != -1) && (rpos != -1)) {
1083
            QString declaredTypename = classItem->name().mid(lpos + 1, rpos - lpos - 1);
1084
            m_qmetatypeDeclaredTypenames.insert(declaredTypename);
1085
        }
1086
    }
1087
1088
    if (TypeDatabase::instance()->isClassRejected(fullClassName)) {
1089
        reason = GenerationDisabled;
1090
    } else if (!type) {
1091
        TypeEntry *te = TypeDatabase::instance()->findType(fullClassName);
1092
        if (te && !te->isComplex())
1093
            reason = RedefinedToNotClass;
1094
        else
1095
            reason = NotInTypeSystem;
1096
    } else if (type->codeGeneration() == TypeEntry::GenerateNothing) {
1097
        reason = GenerationDisabled;
1098
    }
1099
    if (reason != NoReason) {
1100
        m_rejectedClasses.insert(fullClassName, reason);
1101
        return 0;
1102
    }
1103
1104
    if (type->isObject())
1105
        ((ObjectTypeEntry*)type)->setQObject(isQObject(fullClassName));
1106
1107
    AbstractMetaClass* metaClass = createMetaClass();
1108
    metaClass->setTypeEntry(type);
1109
    metaClass->setBaseClassNames(classItem->baseClasses());
1110
    *metaClass += AbstractMetaAttributes::Public;
1111
    if (type->stream())
1112
        metaClass->setStream(true);
1113
1114
    AbstractMetaClass* oldCurrentClass = m_currentClass;
1115
    m_currentClass = metaClass;
1116
1117
    if (type->isContainer())
1118
        ReportHandler::debugSparse(QString("container: '%1'").arg(fullClassName));
1119
    else
1120
        ReportHandler::debugSparse(QString("class: '%1'").arg(metaClass->fullName()));
1121
1122
    TemplateParameterList template_parameters = classItem->templateParameters();
1123
    QList<TypeEntry *> template_args;
1124
    template_args.clear();
1125
    for (int i = 0; i < template_parameters.size(); ++i) {
1126
        const TemplateParameterModelItem &param = template_parameters.at(i);
1127
        TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name(), type->version());
1128
        param_type->setOrdinal(i);
1129
        template_args.append(param_type);
1130
    }
1131
    metaClass->setTemplateArguments(template_args);
1132
1133
    parseQ_Property(metaClass, classItem->propertyDeclarations());
1134
1135
    traverseEnums(model_dynamic_cast<ScopeModelItem>(classItem), metaClass, classItem->enumsDeclarations());
1136
1137
    // Inner classes
1138
    {
1139
        QList<ClassModelItem> innerClasses = classItem->classMap().values();
1140
        foreach (const ClassModelItem &ci, innerClasses) {
1141
            AbstractMetaClass *cl = traverseClass(ci);
1142
            if (cl) {
1143
                cl->setEnclosingClass(metaClass);
1144
                metaClass->addInnerClass(cl);
1145
                m_metaClasses << cl;
1146
            }
1147
        }
1148
1149
    }
1150
1151
    // Go through all typedefs to see if we have defined any
1152
    // specific typedefs to be used as classes.
1153
    TypeAliasList typeAliases = classItem->typeAliases();
1154
    foreach (TypeAliasModelItem typeAlias, typeAliases) {
1155
        AbstractMetaClass* cls = traverseTypeAlias(typeAlias);
1156
        if (cls) {
1157
            cls->setEnclosingClass(metaClass);
1158
            addAbstractMetaClass(cls);
1159
        }
1160
    }
1161
1162
1163
    m_currentClass = oldCurrentClass;
1164
1165
    // Set the default include file name
1166
    if (!type->include().isValid())
1167
        setInclude(type, classItem->fileName());
1168
1169
    return metaClass;
1170
}
1171
1172
void AbstractMetaBuilder::traverseScopeMembers(ScopeModelItem item, AbstractMetaClass* metaClass)
1173
{
1174
    // Classes/Namespace members
1175
    traverseFields(item, metaClass);
1176
    traverseFunctions(item, metaClass);
1177
1178
    // Inner classes
1179
    ClassList innerClasses = item->classMap().values();
1180
    qSort(innerClasses);
1181
    ClassList::iterator it = std::unique(innerClasses.begin(), innerClasses.end());
1182
    innerClasses.erase(it, innerClasses.end());
1183
    foreach (const ClassModelItem& ci, innerClasses)
1184
        traverseClassMembers(ci);
1185
}
1186
1187
AbstractMetaClass* AbstractMetaBuilder::currentTraversedClass(ScopeModelItem item)
1188
{
1189
    QString className = stripTemplateArgs(item->name());
1190
    QString fullClassName = className;
1191
1192
    // This is an inner class
1193
    if (m_currentClass)
1194
        fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName()) + "::" + fullClassName;
1195
1196
    AbstractMetaClass* metaClass = m_metaClasses.findClass(fullClassName);
1197
    if (!metaClass)
1198
        metaClass = m_templates.findClass(fullClassName);
1199
    return metaClass;
1200
}
1201
1202
void AbstractMetaBuilder::traverseClassMembers(ClassModelItem item)
1203
{
1204
    AbstractMetaClass* metaClass = currentTraversedClass(model_dynamic_cast<ScopeModelItem>(item));
1205
    if (!metaClass)
1206
        return;
1207
1208
    AbstractMetaClass* oldCurrentClass = m_currentClass;
1209
    m_currentClass = metaClass;
1210
1211
    // Class members
1212
    traverseScopeMembers(model_dynamic_cast<ScopeModelItem>(item), metaClass);
1213
1214
    m_currentClass = oldCurrentClass;
1215
}
1216
1217
void AbstractMetaBuilder::traverseNamespaceMembers(NamespaceModelItem item)
1218
{
1219
    AbstractMetaClass* metaClass = currentTraversedClass(model_dynamic_cast<ScopeModelItem>(item));
1220
    if (!metaClass)
1221
        return;
1222
1223
    AbstractMetaClass* oldCurrentClass = m_currentClass;
1224
    m_currentClass = metaClass;
1225
1226
    // Namespace members
1227
    traverseScopeMembers(model_dynamic_cast<ScopeModelItem>(item), metaClass);
1228
1229
    // Inner namespaces
1230
    NamespaceList innerNamespaces = item->namespaceMap().values();
1231
    qSort(innerNamespaces);
1232
    NamespaceList::iterator it = std::unique(innerNamespaces.begin(), innerNamespaces.end());
1233
    innerNamespaces.erase(it, innerNamespaces.end());
1234
    foreach (const NamespaceModelItem &ni, innerNamespaces)
1235
        traverseNamespaceMembers(ni);
1236
1237
    m_currentClass = oldCurrentClass;
1238
}
1239
1240
AbstractMetaField* AbstractMetaBuilder::traverseField(VariableModelItem field, const AbstractMetaClass *cls)
1241
{
1242
    QString fieldName = field->name();
1243
    QString className = m_currentClass->typeEntry()->qualifiedCppName();
1244
1245
    // Ignore friend decl.
1246
    if (field->isFriend())
1247
        return 0;
1248
1249
    if (field->accessPolicy() == CodeModel::Private)
1250
        return 0;
1251
1252
    if (TypeDatabase::instance()->isFieldRejected(className, fieldName)) {
1253
        m_rejectedFields.insert(className + "::" + fieldName, GenerationDisabled);
1254
        return 0;
1255
    }
1256
1257
1258
    AbstractMetaField* metaField = createMetaField();
1259
    metaField->setName(fieldName);
1260
    metaField->setEnclosingClass(cls);
1261
1262
    bool ok;
1263
    TypeInfo fieldType = field->type();
1264
    AbstractMetaType *metaType = translateType(fieldType, &ok);
1265
1266
    if (!metaType || !ok) {
1267
        ReportHandler::warning(QString("skipping field '%1::%2' with unmatched type '%3'")
1268
                               .arg(m_currentClass->name())
1269
                               .arg(fieldName)
1270
                               .arg(TypeInfo::resolveType(fieldType, currentScope()->toItem()).qualifiedName().join("::")));
1271
        delete metaField;
1272
        return 0;
1273
    }
1274
1275
    metaField->setType(metaType);
1276
1277
    uint attr = 0;
1278
    if (field->isStatic())
1279
        attr |= AbstractMetaAttributes::Static;
1280
1281
    CodeModel::AccessPolicy policy = field->accessPolicy();
1282
    if (policy == CodeModel::Public)
1283
        attr |= AbstractMetaAttributes::Public;
1284
    else if (policy == CodeModel::Protected)
1285
        attr |= AbstractMetaAttributes::Protected;
1286
    else
1287
        attr |= AbstractMetaAttributes::Private;
1288
    metaField->setAttributes(attr);
1289
1290
    return metaField;
1291
}
1292
1293
void AbstractMetaBuilder::traverseFields(ScopeModelItem scope_item, AbstractMetaClass *metaClass)
1294
{
1295
    foreach (VariableModelItem field, scope_item->variables()) {
1296
        AbstractMetaField* metaField = traverseField(field, metaClass);
1297
1298
        if (metaField && !metaField->isModifiedRemoved()) {
1299
            metaField->setOriginalAttributes(metaField->attributes());
1300
            metaClass->addField(metaField);
1301
        }
1302
    }
1303
}
1304
1305
void AbstractMetaBuilder::setupFunctionDefaults(AbstractMetaFunction* metaFunction, AbstractMetaClass *metaClass)
1306
{
1307
    // Set the default value of the declaring class. This may be changed
1308
    // in fixFunctions later on
1309
    metaFunction->setDeclaringClass(metaClass);
1310
1311
    // Some of the queries below depend on the implementing class being set
1312
    // to function properly. Such as function modifications
1313
    metaFunction->setImplementingClass(metaClass);
1314
1315
    if (metaFunction->name() == "operator_equal")
1316
        metaClass->setHasEqualsOperator(true);
1317
1318
    if (!metaFunction->isFinalInTargetLang()
1319
        && metaFunction->isRemovedFrom(metaClass, TypeSystem::TargetLangCode)) {
1320
        *metaFunction += AbstractMetaAttributes::FinalInCpp;
1321
    }
1322
}
1323
1324
void AbstractMetaBuilder::fixReturnTypeOfConversionOperator(AbstractMetaFunction* metaFunction)
1325
{
1326
    if (!metaFunction->isConversionOperator()
1327
        || metaFunction->implementingClass()->typeEntry() != metaFunction->type()->typeEntry())
1328
        return;
1329
1330
    TypeDatabase* types = TypeDatabase::instance();
1331
    QString castTo = metaFunction->name().remove(QRegExp("^operator ")).trimmed();
1332
1333
    if (castTo.endsWith('&'))
1334
        castTo.chop(1);
1335
    if (castTo.startsWith("const "))
1336
        castTo.remove(0, 6);
1337
1338
    TypeEntry* retType = types->findType(castTo);
1339
    if (!retType)
1340
        return;
1341
1342
    AbstractMetaType* metaType = createMetaType();
1343
    metaType->setTypeEntry(retType);
1344
    metaFunction->replaceType(metaType);
1345
}
1346
1347
static bool _compareAbstractMetaTypes(const AbstractMetaType* type, const AbstractMetaType* other)
1348
{
1349
    if (!type && !other)
1350
        return true;
1351
    if (!type || !other)
1352
        return false;
1353
    return type->typeEntry() == other->typeEntry()
1354
            && type->isConstant() == other->isConstant()
1355
            && type->isReference() == other->isReference()
1356
            && type->indirections() == other->indirections();
1357
}
1358
1359
static bool _compareAbstractMetaFunctions(const AbstractMetaFunction* func, const AbstractMetaFunction* other)
1360
{
1361
    if (!func && !other)
1362
        return true;
1363
    if (!func || !other)
1364
        return false;
1365
    if (func->arguments().count() != other->arguments().count()
1366
        || func->isConstant() != other->isConstant()
1367
        || func->isStatic() != other->isStatic()
1368
        || !_compareAbstractMetaTypes(func->type(), other->type())) {
1369
        return false;
1370
    }
1371
    for (int i = 0; i < func->arguments().count(); ++i) {
1372
        if (!_compareAbstractMetaTypes(func->arguments().at(i)->type(), other->arguments().at(i)->type()))
1373
            return false;
1374
    }
1375
    return true;
1376
}
1377
1378
static bool _fixFunctionModelItemType(TypeInfo& type, const AbstractMetaClass* metaClass)
1379
{
1380
    if (metaClass->templateArguments().isEmpty()
1381
        || type.qualifiedName().isEmpty()
1382
        || type.qualifiedName().first() != metaClass->typeEntry()->qualifiedCppName()) {
1383
        return false;
1384
    }
1385
    QStringList templateTypes;
1386
    foreach (TypeEntry* templateType, metaClass->templateArguments())
1387
        templateTypes << templateType->qualifiedCppName();
1388
    QString fixedTypeName = QString("%1<%2 >").arg(metaClass->typeEntry()->qualifiedCppName()).arg(templateTypes.join(", "));
1389
    type.setQualifiedName(QStringList(fixedTypeName));
1390
    return true;
1391
}
1392
1393
static bool _fixFunctionModelItemTypes(FunctionModelItem& function, const AbstractMetaClass* metaClass)
1394
{
1395
    TypeInfo functionType = function->type();
1396
    bool templateTypeFixed = _fixFunctionModelItemType(functionType, metaClass);
1397
    if (templateTypeFixed)
1398
        function->setType(functionType);
1399
1400
    ArgumentList arguments = function->arguments();
1401
    for (int i = 0; i < arguments.size(); ++i) {
1402
        ArgumentModelItem arg = arguments.at(i);
1403
        TypeInfo type = arg->type();
1404
        bool tmpTypeFixed = _fixFunctionModelItemType(type, metaClass);
1405
        if (tmpTypeFixed)
1406
            arg->setType(type);
1407
        templateTypeFixed |= tmpTypeFixed;
1408
    }
1409
    return templateTypeFixed;
1410
}
1411
1412
void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scopeItem, AbstractMetaClass* metaClass)
1413
{
1414
    foreach (FunctionModelItem function, scopeItem->functions()) {
1415
1416
        // This fixes method's arguments and return types that are templates
1417
        // but the template variable wasn't declared in the C++ header.
1418
        bool templateTypeFixed = _fixFunctionModelItemTypes(function, metaClass);
1419
1420
        AbstractMetaFunction* metaFunction = traverseFunction(function);
1421
1422
        if (!metaFunction)
1423
            continue;
1424
1425
        if (templateTypeFixed) {
1426
            foreach (AbstractMetaFunction* func, metaClass->queryFunctionsByName(metaFunction->name())) {
1427
                if (_compareAbstractMetaFunctions(metaFunction, func)) {
1428
                    delete metaFunction;
1429
                    metaFunction = 0;
1430
                    break;
1431
                }
1432
            }
1433
            if (!metaFunction)
1434
                continue;
1435
        }
1436
1437
        metaFunction->setOriginalAttributes(metaFunction->attributes());
1438
        if (metaClass->isNamespace())
1439
            *metaFunction += AbstractMetaAttributes::Static;
1440
1441
        QPropertySpec *read = 0;
1442
        if (!metaFunction->isSignal() && (read = metaClass->propertySpecForRead(metaFunction->name()))) {
1443
            // Property reader must be in the form "<type> name()"
1444
            if (metaFunction->type() && (read->type() == metaFunction->type()->typeEntry()) && (metaFunction->arguments().size() == 0)) {
1445
                *metaFunction += AbstractMetaAttributes::PropertyReader;
1446
                metaFunction->setPropertySpec(read);
1447
            }
1448
        } else if (QPropertySpec* write = metaClass->propertySpecForWrite(metaFunction->name())) {
1449
            // Property setter must be in the form "void name(<type>)"
1450
            // make sure the function was created with all aguments, some argument can be missing during the pareser because of errors on typesystem
1451
            if ((!metaFunction->type()) && (metaFunction->arguments().size() == 1) && (write->type() == metaFunction->arguments().at(0)->type()->typeEntry())) {
1452
                *metaFunction += AbstractMetaAttributes::PropertyWriter;
1453
                metaFunction->setPropertySpec(write);
1454
            }
1455
        } else if (QPropertySpec* reset = metaClass->propertySpecForReset(metaFunction->name())) {
1456
            // Property resetter must be in the form "void name()"
1457
            if ((!metaFunction->type()) && (metaFunction->arguments().size() == 0)) {
1458
                *metaFunction += AbstractMetaAttributes::PropertyResetter;
1459
                metaFunction->setPropertySpec(reset);
1460
            }
1461
        }
1462
1463
        // Can not use metaFunction->isCopyConstructor() because
1464
        // the function wasn't assigned to its owner class yet.
1465
        bool isCopyCtor = false;
1466
        if (metaFunction->isConstructor() && metaFunction->arguments().size() == 1) {
1467
            const AbstractMetaType* argType = metaFunction->arguments().first()->type();
1468
            isCopyCtor = argType->isConstant()
1469
                         && argType->isReference()
1470
                         && argType->typeEntry()->name() == metaFunction->name();
1471
        }
1472
1473
        bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate();
1474
        bool isInvalidConstructor = metaFunction->isConstructor()
1475
                                    && ((metaFunction->isPrivate() && !isCopyCtor) || metaFunction->isInvalid());
1476
1477
        if ((isInvalidDestructor || isInvalidConstructor)
1478
            && !metaClass->hasNonPrivateConstructor()) {
1479
            *metaClass += AbstractMetaAttributes::Final;
1480
        } else if (metaFunction->isConstructor() && !metaFunction->isPrivate()) {
1481
            *metaClass -= AbstractMetaAttributes::Final;
1482
            metaClass->setHasNonPrivateConstructor(true);
1483
        }
1484
1485
        // Classes with virtual destructors should always have a shell class
1486
        // (since we aren't registering the destructors, we need this extra check)
1487
        if (metaFunction->isDestructor() && !metaFunction->isFinal())
1488
            metaClass->setForceShellClass(true);
1489
1490
        if (!metaFunction->isDestructor()
1491
            && !metaFunction->isInvalid()
1492
            && !(metaFunction->isPrivate() && metaFunction->isConstructor() && !isCopyCtor)) {
1493
1494
            setupFunctionDefaults(metaFunction, metaClass);
1495
1496
            if (metaFunction->isSignal() && metaClass->hasSignal(metaFunction)) {
1497
                QString warn = QString("signal '%1' in class '%2' is overloaded.")
1498
                               .arg(metaFunction->name()).arg(metaClass->name());
1499
                ReportHandler::warning(warn);
1500
            }
1501
1502
            if (metaFunction->isSignal() && !metaClass->isQObject()) {
1503
                QString warn = QString("signal '%1' in non-QObject class '%2'")
1504
                               .arg(metaFunction->name()).arg(metaClass->name());
1505
                ReportHandler::warning(warn);
1506
            }
1507
1508
            if (metaFunction->isConversionOperator())
1509
                fixReturnTypeOfConversionOperator(metaFunction);
1510
1511
            metaClass->addFunction(metaFunction);
1512
            applyFunctionModifications(metaFunction);
1513
        } else if (metaFunction->isDestructor()) {
1514
            metaClass->setHasPrivateDestructor(metaFunction->isPrivate());
1515
            metaClass->setHasProtectedDestructor(metaFunction->isProtected());
1516
            metaClass->setHasVirtualDestructor(metaFunction->isVirtual());
1517
        }
1518
        if (!metaFunction->ownerClass()) {
1519
            delete metaFunction;
1520
            metaFunction = 0;
1521
        }
1522
    }
1523
1524
    fillAddedFunctions(metaClass);
1525
}
1526
1527
void AbstractMetaBuilder::fillAddedFunctions(AbstractMetaClass* metaClass)
1528
{
1529
    // Add the functions added by the typesystem
1530
    foreach (AddedFunction addedFunc, metaClass->typeEntry()->addedFunctions())
1531
        traverseFunction(addedFunc, metaClass);
1532
}
1533
1534
void AbstractMetaBuilder::applyFunctionModifications(AbstractMetaFunction* func)
1535
{
1536
    FunctionModificationList mods = func->modifications(func->implementingClass());
1537
    AbstractMetaFunction& funcRef = *func;
1538
    foreach (FunctionModification mod, mods) {
1539
        if (mod.isRenameModifier()) {
1540
            func->setOriginalName(func->name());
1541
            func->setName(mod.renamedTo());
1542
        } else if (mod.isAccessModifier()) {
1543
            funcRef -= AbstractMetaAttributes::Public;
1544
            funcRef -= AbstractMetaAttributes::Protected;
1545
            funcRef -= AbstractMetaAttributes::Private;
1546
            funcRef -= AbstractMetaAttributes::Friendly;
1547
1548
            if (mod.isPublic())
1549
                funcRef += AbstractMetaAttributes::Public;
1550
            else if (mod.isProtected())
1551
                funcRef += AbstractMetaAttributes::Protected;
1552
            else if (mod.isPrivate())
1553
                funcRef += AbstractMetaAttributes::Private;
1554
            else if (mod.isFriendly())
1555
                funcRef += AbstractMetaAttributes::Friendly;
1556
        }
1557
1558
        if (mod.isFinal())
1559
            funcRef += AbstractMetaAttributes::FinalInTargetLang;
1560
        else if (mod.isNonFinal())
1561
            funcRef -= AbstractMetaAttributes::FinalInTargetLang;
1562
    }
1563
}
1564
1565
bool AbstractMetaBuilder::setupInheritance(AbstractMetaClass *metaClass)
1566
{
1567
    Q_ASSERT(!metaClass->isInterface());
1568
1569
    if (m_setupInheritanceDone.contains(metaClass))
1570
        return true;
1571
1572
    m_setupInheritanceDone.insert(metaClass);
1573
1574
    QStringList baseClasses = metaClass->baseClassNames();
1575
1576
    TypeDatabase* types = TypeDatabase::instance();
1577
1578
    // we only support our own containers and ONLY if there is only one baseclass
1579
    if (baseClasses.size() == 1 && baseClasses.first().count('<') == 1) {
1580
        QStringList scope = metaClass->typeEntry()->qualifiedCppName().split("::");
1581
        scope.removeLast();
1582
        for (int i = scope.size(); i >= 0; --i) {
1583
            QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join("::") + "::" : QString();
1584
            QString completeName = prefix + baseClasses.first();
1585
            TypeParser::Info info = TypeParser::parse(completeName);
1586
            QString baseName = info.qualified_name.join("::");
1587
1588
            AbstractMetaClass* templ = 0;
1589
            foreach (AbstractMetaClass *c, m_templates) {
1590
                if (c->typeEntry()->name() == baseName) {
1591
                    templ = c;
1592
                    break;
1593
                }
1594
            }
1595
1596
            if (!templ)
1597
                templ = m_metaClasses.findClass(baseName);
1598
1599
            if (templ) {
1600
                setupInheritance(templ);
1601
                inheritTemplate(metaClass, templ, info);
1602
                metaClass->typeEntry()->setBaseContainerType(templ->typeEntry());
1603
                return true;
1604
            }
1605
            ComplexTypeEntry* baseContainerType = types->findContainerType(baseName);
1606
            if (baseContainerType)
1607
                metaClass->typeEntry()->setBaseContainerType(baseContainerType);
1608
        }
1609
1610
        ReportHandler::warning(QString("template baseclass '%1' of '%2' is not known")
1611
                               .arg(baseClasses.first())
1612
                               .arg(metaClass->name()));
1613
        return false;
1614
    }
1615
1616
    int primary = -1;
1617
    int primaries = 0;
1618
    for (int i = 0; i < baseClasses.size(); ++i) {
1619
1620
        if (types->isClassRejected(baseClasses.at(i)))
1621
            continue;
1622
1623
        TypeEntry* baseClassEntry = types->findType(baseClasses.at(i));
1624
        if (!baseClassEntry)
1625
            ReportHandler::warning(QString("class '%1' inherits from unknown base class '%2'")
1626
                                   .arg(metaClass->name()).arg(baseClasses.at(i)));
1627
1628
        // true for primary base class
1629
        else if (!baseClassEntry->designatedInterface()) {
1630
            primaries++;
1631
            primary = i;
1632
        }
1633
    }
1634
1635
    if (primary >= 0) {
1636
        AbstractMetaClass* baseClass = m_metaClasses.findClass(baseClasses.at(primary));
1637
        if (!baseClass) {
1638
            ReportHandler::warning(QString("unknown baseclass for '%1': '%2'")
1639
                                   .arg(metaClass->name())
1640
                                   .arg(baseClasses.at(primary)));
1641
            return false;
1642
        }
1643
        metaClass->setBaseClass(baseClass);
1644
    }
1645
1646
    for (int i = 0; i < baseClasses.size(); ++i) {
1647
        if (types->isClassRejected(baseClasses.at(i)))
1648
            continue;
1649
1650
        if (i != primary) {
1651
            AbstractMetaClass* baseClass = m_metaClasses.findClass(baseClasses.at(i));
1652
            if (!baseClass) {
1653
                ReportHandler::warning(QString("class not found for setup inheritance '%1'").arg(baseClasses.at(i)));
1654
                return false;
1655
            }
1656
1657
            setupInheritance(baseClass);
1658
1659
            QString interfaceName = baseClass->isInterface() ? InterfaceTypeEntry::interfaceName(baseClass->name()) : baseClass->name();
1660
            AbstractMetaClass* iface = m_metaClasses.findClass(interfaceName);
1661
            if (!iface) {
1662
                ReportHandler::warning(QString("unknown interface for '%1': '%2'")
1663
                                       .arg(metaClass->name())
1664
                                       .arg(interfaceName));
1665
                return false;
1666
            }
1667
            metaClass->addInterface(iface);
1668
1669
            AbstractMetaClassList interfaces = iface->interfaces();
1670
            foreach (AbstractMetaClass* iface, interfaces)
1671
                metaClass->addInterface(iface);
1672
        }
1673
    }
1674
1675
    return true;
1676
}
1677
1678
void AbstractMetaBuilder::traverseEnums(ScopeModelItem scopeItem, AbstractMetaClass* metaClass, const QStringList &enumsDeclarations)
1679
{
1680
    EnumList enums = scopeItem->enums();
1681
    foreach (EnumModelItem enumItem, enums) {
1682
        AbstractMetaEnum* metaEnum = traverseEnum(enumItem, metaClass, QSet<QString>::fromList(enumsDeclarations));
1683
        if (metaEnum) {
1684
            metaClass->addEnum(metaEnum);
1685
            metaEnum->setEnclosingClass(metaClass);
1686
        }
1687
    }
1688
}
1689
1690
AbstractMetaFunction* AbstractMetaBuilder::traverseFunction(const AddedFunction& addedFunc)
1691
{
1692
    return traverseFunction(addedFunc, 0);
1693
}
1694
1695
AbstractMetaFunction* AbstractMetaBuilder::traverseFunction(const AddedFunction& addedFunc, AbstractMetaClass* metaClass)
1696
{
1697
    AbstractMetaFunction* metaFunction = createMetaFunction();
1698
    metaFunction->setConstant(addedFunc.isConstant());
1699
    metaFunction->setName(addedFunc.name());
1700
    metaFunction->setOriginalName(addedFunc.name());
1701
    int visibility = addedFunc.access() == AddedFunction::Public ? AbstractMetaAttributes::Public : AbstractMetaAttributes::Protected;
1702
    metaFunction->setVisibility(visibility);
1703
    metaFunction->setUserAdded(true);
1704
    AbstractMetaAttributes::Attribute isStatic = addedFunc.isStatic() ? AbstractMetaFunction::Static : AbstractMetaFunction::None;
1705
    metaFunction->setAttributes(metaFunction->attributes() | AbstractMetaAttributes::Final | isStatic);
1706
    metaFunction->setType(translateType(addedFunc.version(), addedFunc.returnType()));
1707
1708
1709
    QList<AddedFunction::TypeInfo> args = addedFunc.arguments();
1710
    AbstractMetaArgumentList metaArguments;
1711
1712
    for (int i = 0; i < args.count(); ++i) {
1713
        AddedFunction::TypeInfo& typeInfo = args[i];
1714
        AbstractMetaArgument* metaArg = createMetaArgument();
1715
        AbstractMetaType* type = translateType(addedFunc.version(), typeInfo);
1716
        decideUsagePattern(type);
1717
        metaArg->setType(type);
1718
        metaArg->setArgumentIndex(i);
1719
        metaArg->setDefaultValueExpression(typeInfo.defaultValue);
1720
        metaArg->setOriginalDefaultValueExpression(typeInfo.defaultValue);
1721
        metaArguments.append(metaArg);
1722
    }
1723
1724
    metaFunction->setArguments(metaArguments);
1725
    if (metaFunction->isOperatorOverload() && !metaFunction->isCallOperator()) {
1726
        if (metaArguments.size() > 2) {
1727
            ReportHandler::warning("An operator overload need to have 0, 1 or 2 arguments if it's reverse.");
1728
        } else if (metaArguments.size() == 2) {
1729
            // Check if it's a reverse operator
1730
            if (metaArguments[1]->type()->typeEntry() == metaClass->typeEntry()) {
1731
                metaFunction->setReverseOperator(true);
1732
                // we need to call these two function to cache the old signature (with two args)
1733
                // we do this buggy behaviour to comply with the original apiextractor buggy behaviour.
1734
                metaFunction->signature();
1735
                metaFunction->minimalSignature();
1736
                metaArguments.removeLast();
1737
                metaFunction->setArguments(metaArguments);
1738
            } else {
1739
                ReportHandler::warning("Operator overload can have two arguments only if it's a reverse operator!");
1740
            }
1741
        }
1742
    }
1743
1744
1745
    // Find the correct default values
1746
    for (int i = 0; i < metaArguments.size(); ++i) {
1747
        AbstractMetaArgument* metaArg = metaArguments.at(i);
1748
1749
        //use relace-default-expression for set default value
1750
        QString replacedExpression;
1751
        if (m_currentClass)
1752
            replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1);
1753
1754
        if (!replacedExpression.isEmpty()) {
1755
            QString expr = replacedExpression;
1756
            if (!metaFunction->removedDefaultExpression(m_currentClass, i + 1)) {
1757
                metaArg->setDefaultValueExpression(expr);
1758
                metaArg->setOriginalDefaultValueExpression(expr);
1759
1760
                if (metaArg->type()->isEnum() || metaArg->type()->isFlags())
1761
                    m_enumDefaultArguments << QPair<AbstractMetaArgument*, AbstractMetaFunction*>(metaArg, metaFunction);
1762
            }
1763
        }
1764
    }
1765
1766
    metaFunction->setOriginalAttributes(metaFunction->attributes());
1767
    fixArgumentNames(metaFunction);
1768
1769
    if (metaClass) {
1770
        const AbstractMetaArgumentList fargs = metaFunction->arguments();
1771
        if (metaClass->isNamespace())
1772
            *metaFunction += AbstractMetaFunction::Static;
1773
        if (metaFunction->name() == metaClass->name()) {
1774
            metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction);
1775
            if (fargs.size() == 1 && fargs.first()->type()->typeEntry()->isCustom())
1776
                metaFunction->setExplicit(true);
1777
        } else {
1778
            metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction);
1779
        }
1780
1781
        metaFunction->setDeclaringClass(metaClass);
1782
        metaFunction->setImplementingClass(metaClass);
1783
        metaClass->addFunction(metaFunction);
1784
        metaClass->setHasNonPrivateConstructor(true);
1785
    }
1786
1787
    return metaFunction;
1788
}
1789
1790
void AbstractMetaBuilder::fixArgumentNames(AbstractMetaFunction* func)
1791
{
1792
    if (func->arguments().isEmpty())
1793
        return;
1794
    foreach (FunctionModification mod, func->modifications(m_currentClass)) {
1795
        foreach (ArgumentModification argMod, mod.argument_mods) {
1796
            if (!argMod.renamed_to.isEmpty()) {
1797
                AbstractMetaArgument* arg = func->arguments().at(argMod.index - 1);
1798
                arg->setOriginalName(arg->name());
1799
                arg->setName(argMod.renamed_to, false);
1800
            }
1801
        }
1802
    }
1803
1804
    int i = 1;
1805
    foreach (AbstractMetaArgument* arg, func->arguments()) {
1806
        if (arg->name().isEmpty())
1807
            arg->setName("arg__" + QString::number(i), false);
1808
        ++i;
1809
    }
1810
}
1811
1812
AbstractMetaFunction* AbstractMetaBuilder::traverseFunction(FunctionModelItem functionItem)
1813
{
1814
    QString functionName = functionItem->name();
1815
    QString className;
1816
    if (m_currentClass)
1817
        className = m_currentClass->typeEntry()->qualifiedCppName();
1818
1819
    if (TypeDatabase::instance()->isFunctionRejected(className, functionName)) {
1820
        m_rejectedFunctions.insert(className + "::" + functionName, GenerationDisabled);
1821
        return 0;
1822
    }
1823
1824
    Q_ASSERT(functionItem->functionType() == CodeModel::Normal
1825
             || functionItem->functionType() == CodeModel::Signal
1826
             || functionItem->functionType() == CodeModel::Slot);
1827
1828
    if (functionItem->isFriend())
1829
        return 0;
1830
1831
    AbstractMetaFunction* metaFunction = createMetaFunction();
1832
    metaFunction->setConstant(functionItem->isConstant());
1833
1834
    ReportHandler::debugMedium(QString(" - %2()").arg(functionName));
1835
1836
    metaFunction->setName(functionName);
1837
    metaFunction->setOriginalName(functionItem->name());
1838
1839
    if (functionItem->isAbstract())
1840
        *metaFunction += AbstractMetaAttributes::Abstract;
1841
1842
    if (!metaFunction->isAbstract())
1843
        *metaFunction += AbstractMetaAttributes::Native;
1844
1845
    if (!functionItem->isVirtual())
1846
        *metaFunction += AbstractMetaAttributes::Final;
1847
1848
    if (functionItem->isInvokable())
1849
        *metaFunction += AbstractMetaAttributes::Invokable;
1850
1851
    if (functionItem->isStatic()) {
1852
        *metaFunction += AbstractMetaAttributes::Static;
1853
        *metaFunction += AbstractMetaAttributes::Final;
1854
    }
1855
1856
    // Access rights
1857
    if (functionItem->accessPolicy() == CodeModel::Public)
1858
        *metaFunction += AbstractMetaAttributes::Public;
1859
    else if (functionItem->accessPolicy() == CodeModel::Private)
1860
        *metaFunction += AbstractMetaAttributes::Private;
1861
    else
1862
        *metaFunction += AbstractMetaAttributes::Protected;
1863
1864
1865
    QString strippedClassName = className;
1866
    int cc_pos = strippedClassName.lastIndexOf("::");
1867
    if (cc_pos > 0)
1868
        strippedClassName = strippedClassName.mid(cc_pos + 2);
1869
1870
    TypeInfo functionType = functionItem->type();
1871
    if (functionName.startsWith('~')) {
1872
        metaFunction->setFunctionType(AbstractMetaFunction::DestructorFunction);
1873
        metaFunction->setInvalid(true);
1874
    } else if (stripTemplateArgs(functionName) == strippedClassName) {
1875
        metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction);
1876
        metaFunction->setExplicit(functionItem->isExplicit());
1877
        metaFunction->setName(m_currentClass->name());
1878
    } else {
1879
        bool ok;
1880
        AbstractMetaType* type = translateType(functionType, &ok);
1881
1882
        if (!ok) {
1883
            Q_ASSERT(type == 0);
1884
            ReportHandler::warning(QString("skipping function '%1::%2', unmatched return type '%3'")
1885
                                   .arg(className)
1886
                                   .arg(functionItem->name())
1887
                                   .arg(functionItem->type().toString()));
1888
            m_rejectedFunctions[className + "::" + functionName] =
1889
                UnmatchedReturnType;
1890
            metaFunction->setInvalid(true);
1891
            return metaFunction;
1892
        }
1893
1894
        metaFunction->setType(type);
1895
1896
        if (functionItem->functionType() == CodeModel::Signal)
1897
            metaFunction->setFunctionType(AbstractMetaFunction::SignalFunction);
1898
        else if (functionItem->functionType() == CodeModel::Slot)
1899
            metaFunction->setFunctionType(AbstractMetaFunction::SlotFunction);
1900
    }
1901
1902
    ArgumentList arguments = functionItem->arguments();
1903
1904
    if (arguments.size() == 1) {
1905
        ArgumentModelItem arg = arguments.at(0);
1906
        TypeInfo type = arg->type();
1907
        if (type.qualifiedName().first() == "void" && type.indirections() == 0)
1908
            delete arguments.takeFirst();
1909
    }
1910
1911
    AbstractMetaArgumentList metaArguments;
1912
1913
    for (int i = 0; i < arguments.size(); ++i) {
1914
        ArgumentModelItem arg = arguments.at(i);
1915
1916
        bool ok;
1917
        AbstractMetaType* metaType = translateType(arg->type(), &ok);
1918
        if (!ok) {
1919
            Q_ASSERT(metaType == 0);
1920
            ReportHandler::warning(QString("skipping function '%1::%2', "
1921
                                           "unmatched parameter type '%3'")
1922
                                   .arg(className)
1923
                                   .arg(functionItem->name())
1924
                                   .arg(arg->type().toString()));
1925
            m_rejectedFunctions[className + "::" + functionName] =
1926
                UnmatchedArgumentType;
1927
            metaFunction->setInvalid(true);
1928
            return metaFunction;
1929
        }
1930
1931
        AbstractMetaArgument* metaArgument = createMetaArgument();
1932
1933
        metaArgument->setType(metaType);
1934
        metaArgument->setName(arg->name());
1935
        metaArgument->setArgumentIndex(i);
1936
        metaArguments << metaArgument;
1937
    }
1938
1939
    metaFunction->setArguments(metaArguments);
1940
1941
    // Find the correct default values
1942
    for (int i = 0; i < arguments.size(); ++i) {
1943
        ArgumentModelItem arg = arguments.at(i);
1944
        AbstractMetaArgument* metaArg = metaArguments.at(i);
1945
1946
        //use relace-default-expression for set default value
1947
        QString replacedExpression;
1948
        if (m_currentClass) {
1949
            replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1);
1950
        } else {
1951
            FunctionModificationList mods = TypeDatabase::instance()->functionModifications(metaFunction->minimalSignature());
1952
            if (!mods.isEmpty()) {
1953
                QList<ArgumentModification> argMods = mods.first().argument_mods;
1954
                if (!argMods.isEmpty())
1955
                    replacedExpression = argMods.first().replacedDefaultExpression;
1956
            }
1957
        }
1958
1959
        bool hasDefaultValue = false;
1960
        if (arg->defaultValue() || !replacedExpression.isEmpty()) {
1961
            QString expr = arg->defaultValueExpression();
1962
            expr = fixDefaultValue(arg, metaArg->type(), metaFunction, m_currentClass, i);
1963
            metaArg->setOriginalDefaultValueExpression(expr);
1964
1965
            if (metaFunction->removedDefaultExpression(m_currentClass, i + 1)) {
1966
                expr = "";
1967
            } else if (!replacedExpression.isEmpty()) {
1968
                expr = replacedExpression;
1969
            }
1970
            metaArg->setDefaultValueExpression(expr);
1971
1972
            if (metaArg->type()->isEnum() || metaArg->type()->isFlags())
1973
                m_enumDefaultArguments << QPair<AbstractMetaArgument *, AbstractMetaFunction *>(metaArg, metaFunction);
1974
1975
            hasDefaultValue = !expr.isEmpty();
1976
        }
1977
1978
        //Check for missing argument name
1979
        if (hasDefaultValue
1980
            && !metaArg->hasName()
1981
            && !metaFunction->isOperatorOverload()
1982
            && !metaFunction->isSignal()
1983
            && metaFunction->argumentName(i+1, false, m_currentClass).isEmpty()) {
1984
            ReportHandler::warning(QString("Argument %1 on function '%2::%3' has default expression but does not have name.").arg(i+1).arg(className).arg(metaFunction->minimalSignature()));
1985
        }
1986
1987
    }
1988
1989
    fixArgumentNames(metaFunction);
1990
    return metaFunction;
1991
}
1992
1993
AbstractMetaType* AbstractMetaBuilder::translateType(double vr, const AddedFunction::TypeInfo& typeInfo)
1994
{
1995
    Q_ASSERT(!typeInfo.name.isEmpty());
1996
    TypeDatabase* typeDb = TypeDatabase::instance();
1997
    TypeEntry* type;
1998
1999
    QString typeName = typeInfo.name;
2000
2001
    if (typeName == "void")
2002
        return 0;
2003
2004
    type = typeDb->findType(typeName);
2005
2006
    // test if the type is a template, like a container
2007
    bool isTemplate = false;
2008
    QString templateArg;
2009
    if (!type) {
2010
        QRegExp r("(.*)<(.*)>$");
2011
        if (r.indexIn(typeInfo.name) != -1) {
2012
            templateArg = r.cap(2);
2013
            if (templateArg.contains(','))
2014
                ReportHandler::warning("add-function tag doesn't support container types with more than one argument or template arguments.");
2015
            else
2016
                isTemplate = (type = typeDb->findContainerType(r.cap(1)));
2017
        }
2018
    }
2019
2020
    if (!type) {
2021
        QStringList candidates;
2022
        SingleTypeEntryHash entries = typeDb->entries();
2023
        foreach (QString candidate, entries.keys()) {
2024
            // Let's try to find the type in different scopes.
2025
            if (candidate.endsWith("::"+typeName))
2026
                candidates << candidate;
2027
        }
2028
2029
        QString msg = QString("Type '%1' wasn't found in the type database.\n").arg(typeName);
2030
2031
        if (candidates.isEmpty())
2032
            qFatal(qPrintable(QString(msg + "Declare it in the type system using the proper <*-type> tag.")), NULL);
2033
2034
        msg += "Remember to inform the full qualified name for the type you want to use.\nCandidates are:\n";
2035
        candidates.sort();
2036
        foreach (const QString& candidate, candidates) {
2037
            msg += "    " + candidate + "\n";
2038
        }
2039
        qFatal(qPrintable(msg), NULL);
2040
    }
2041
2042
    AbstractMetaType* metaType = createMetaType();
2043
    metaType->setTypeEntry(type);
2044
    metaType->setIndirections(typeInfo.indirections);
2045
    metaType->setReference(typeInfo.isReference);
2046
    metaType->setConstant(typeInfo.isConstant);
2047
    if (isTemplate) {
2048
        type = typeDb->findType(templateArg);
2049
        if (type) {
2050
            AbstractMetaType* metaArgType = createMetaType();
2051
            metaArgType->setTypeEntry(type);
2052
            metaType->addInstantiation(metaArgType);
2053
            metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
2054
        }
2055
    }
2056
2057
    return metaType;
2058
}
2059
2060
static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaClass, const QString& qualifiedName)
2061
{
2062
    const TypeEntry* type = 0;
2063
    QStringList context = metaClass->qualifiedCppName().split("::");
2064
    while(!type && (context.size() > 0) ) {
2065
        type = TypeDatabase::instance()->findType(context.join("::") + "::" + qualifiedName);
2066
        context.removeLast();
2067
    }
2068
    return type;
2069
}
2070
2071
AbstractMetaType* AbstractMetaBuilder::translateType(const TypeInfo& _typei, bool *ok, bool resolveType, bool resolveScope)
2072
{
2073
    Q_ASSERT(ok);
2074
    *ok = true;
2075
2076
    // 1. Test the type info without resolving typedefs in case this is present in the
2077
    //    type system
2078
    TypeInfo typei;
2079
    if (resolveType) {
2080
        bool ok;
2081
        AbstractMetaType* t = translateType(_typei, &ok, false, resolveScope);
2082
        if (t && ok)
2083
            return t;
2084
        Q_ASSERT(t == 0);
2085
    }
2086
2087
    if (!resolveType) {
2088
        typei = _typei;
2089
    } else {
2090
        // Go through all parts of the current scope (including global namespace)
2091
        // to resolve typedefs. The parser does not properly resolve typedefs in
2092
        // the global scope when they are referenced from inside a namespace.
2093
        // This is a work around to fix this bug since fixing it in resolveType
2094
        // seemed non-trivial
2095
        int i = m_scopes.size() - 1;
2096
        while (i >= 0) {
2097
            typei = TypeInfo::resolveType(_typei, m_scopes.at(i--)->toItem());
2098
            if (typei.qualifiedName().join("::") != _typei.qualifiedName().join("::"))
2099
                break;
2100
        }
2101
2102
    }
2103
2104
    if (typei.isFunctionPointer()) {
2105
        *ok = false;
2106
        return 0;
2107
    }
2108
2109
    TypeParser::Info typeInfo = TypeParser::parse(typei.toString());
2110
    if (typeInfo.is_busted) {
2111
        *ok = false;
2112
        return 0;
2113
    }
2114
2115
    // 2. Handle pointers specified as arrays with unspecified size
2116
    bool arrayOfUnspecifiedSize = false;
2117
    if (typeInfo.arrays.size() > 0) {
2118
        arrayOfUnspecifiedSize = true;
2119
        for (int i = 0; i < typeInfo.arrays.size(); ++i)
2120
            arrayOfUnspecifiedSize = arrayOfUnspecifiedSize && typeInfo.arrays.at(i).isEmpty();
2121
2122
        if (!arrayOfUnspecifiedSize) {
2123
            TypeInfo newInfo;
2124
            //newInfo.setArguments(typei.arguments());
2125
            newInfo.setIndirections(typei.indirections());
2126
            newInfo.setConstant(typei.isConstant());
2127
            newInfo.setFunctionPointer(typei.isFunctionPointer());
2128
            newInfo.setQualifiedName(typei.qualifiedName());
2129
            newInfo.setReference(typei.isReference());
2130
            newInfo.setVolatile(typei.isVolatile());
2131
2132
            AbstractMetaType* elementType = translateType(newInfo, ok);
2133
            if (!(*ok))
2134
                return 0;
2135
2136
            for (int i = typeInfo.arrays.size() - 1; i >= 0; --i) {
2137
                QString s = typeInfo.arrays.at(i);
2138
                bool _ok;
2139
                int elems = findOutValueFromString(s, _ok);
2140
2141
                AbstractMetaType* arrayType = createMetaType();
2142
                arrayType->setArrayElementCount(elems);
2143
                arrayType->setArrayElementType(elementType);
2144
                arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry() , elementType->typeEntry()->version()));
2145
                decideUsagePattern(arrayType);
2146
2147
                elementType = arrayType;
2148
            }
2149
2150
            return elementType;
2151
        }  else {
2152
            typeInfo.indirections += typeInfo.arrays.size();
2153
        }
2154
    }
2155
2156
    QStringList qualifierList = typeInfo.qualified_name;
2157
    if (qualifierList.isEmpty()) {
2158
        ReportHandler::warning(QString("horribly broken type '%1'").arg(_typei.toString()));
2159
        *ok = false;
2160
        return 0;
2161
    }
2162
2163
    QString qualifiedName = qualifierList.join("::");
2164
    QString name = qualifierList.takeLast();
2165
2166
    // 3. Special case 'void' type
2167
    if (name == "void" && !typeInfo.indirections)
2168
        return 0;
2169
2170
    // 4. Special case QFlags (include instantiation in name)
2171
    if (qualifiedName == "QFlags")
2172
        qualifiedName = typeInfo.toString();
2173
2174
    const TypeEntry *type = 0;
2175
    // 5. Try to find the type
2176
2177
    // 5.1 - Try first using the current scope
2178
    if (m_currentClass) {
2179
        type = findTypeEntryUsingContext(m_currentClass, qualifiedName);
2180
2181
        // 5.1.1 - Try using the class parents' scopes
2182
        if (!type && !m_currentClass->baseClassNames().isEmpty()) {
2183
            foreach (const AbstractMetaClass* cls, getBaseClasses(m_currentClass)) {
2184
                type = findTypeEntryUsingContext(cls, qualifiedName);
2185
                if (type)
2186
                    break;
2187
            }
2188
        }
2189
    }
2190
2191
    // 5.2 - Try without scope
2192
    if (!type)
2193
        type = TypeDatabase::instance()->findType(qualifiedName);
2194
2195
    // 6. No? Try looking it up as a flags type
2196
    if (!type)
2197
        type = TypeDatabase::instance()->findFlagsType(qualifiedName);
2198
2199
    // 7. No? Try looking it up as a container type
2200
    if (!type)
2201
        type = TypeDatabase::instance()->findContainerType(name);
2202
2203
    // 8. No? Check if the current class is a template and this type is one
2204
    //    of the parameters.
2205
    if (!type && m_currentClass) {
2206
        QList<TypeEntry *> template_args = m_currentClass->templateArguments();
2207
        foreach (TypeEntry *te, template_args) {
2208
            if (te->name() == qualifiedName)
2209
                type = te;
2210
        }
2211
    }
2212
2213
    // 9. Try finding the type by prefixing it with the current
2214
    //    context and all baseclasses of the current context
2215
    if (!type && !TypeDatabase::instance()->isClassRejected(qualifiedName) && m_currentClass && resolveScope) {
2216
        QStringList contexts;
2217
        contexts.append(m_currentClass->qualifiedCppName());
2218
        contexts.append(currentScope()->qualifiedName().join("::"));
2219
2220
2221
        TypeInfo info = typei;
2222
        bool subclassesDone = false;
2223
        while (!contexts.isEmpty() && !type) {
2224
            type = TypeDatabase::instance()->findType(contexts.at(0) + "::" + qualifiedName);
2225
            contexts.pop_front();
2226
2227
            // 10. Last resort: Special cased prefix of Qt namespace since the meta object implicitly inherits this, so
2228
            //     enum types from there may be addressed without any scope resolution in properties.
2229
            if (!contexts.size() && !subclassesDone) {
2230
                contexts << "Qt";
2231
                subclassesDone = true;
2232
            }
2233
        }
2234
2235
    }
2236
2237
    if (!type) {
2238
        *ok = false;
2239
        return 0;
2240
    }
2241
2242
    // Used to for diagnostics later...
2243
    m_usedTypes << type;
2244
2245
    // These are only implicit and should not appear in code...
2246
    Q_ASSERT(!type->isInterface());
2247
2248
    AbstractMetaType* metaType = createMetaType();
2249
    metaType->setTypeEntry(type);
2250
    metaType->setIndirections(typeInfo.indirections);
2251
    metaType->setReference(typeInfo.is_reference);
2252
    metaType->setConstant(typeInfo.is_constant);
2253
    metaType->setOriginalTypeDescription(_typei.toString());
2254
2255
    foreach (const TypeParser::Info &ta, typeInfo.template_instantiations) {
2256
        TypeInfo info;
2257
        info.setConstant(ta.is_constant);
2258
        info.setReference(ta.is_reference);
2259
        info.setIndirections(ta.indirections);
2260
2261
        info.setFunctionPointer(false);
2262
        info.setQualifiedName(ta.instantiationName().split("::"));
2263
2264
        AbstractMetaType* targType = translateType(info, ok);
2265
        if (!(*ok)) {
2266
            delete metaType;
2267
            return 0;
2268
        }
2269
2270
        metaType->addInstantiation(targType, true);
2271
    }
2272
2273
    // The usage pattern *must* be decided *after* the possible template
2274
    // instantiations have been determined, or else the absence of
2275
    // such instantiations will break the caching scheme of
2276
    // AbstractMetaType::cppSignature().
2277
    decideUsagePattern(metaType);
2278
2279
    return metaType;
2280
}
2281
2282
2283
int AbstractMetaBuilder::findOutValueFromString(const QString& stringValue, bool& ok)
2284
{
2285
    int value = stringValue.toInt(&ok);
2286
    if (ok)
2287
        return value;
2288
2289
    if (stringValue == "true" || stringValue == "false") {
2290
        ok = true;
2291
        return (stringValue == "true");
2292
    }
2293
2294
    // This is a very lame way to handle expression evaluation,
2295
    // but it is not critical and will do for the time being.
2296
    static QRegExp variableNameRegExp("^[a-zA-Z_][a-zA-Z0-9_]*$");
2297
    if (!variableNameRegExp.exactMatch(stringValue)) {
2298
        ok = true;
2299
        return 0;
2300
    }
2301
2302
    AbstractMetaEnumValue* enumValue = m_metaClasses.findEnumValue(stringValue);
2303
    if (enumValue) {
2304
        ok = true;
2305
        return enumValue->value();
2306
    }
2307
2308
    foreach (AbstractMetaEnum* metaEnum, m_globalEnums) {
2309
        foreach (AbstractMetaEnumValue* ev, metaEnum->values()) {
2310
            if (ev->name() == stringValue) {
2311
                ok = true;
2312
                return ev->value();
2313
            }
2314
        }
2315
    }
2316
2317
    ok = false;
2318
    return 0;
2319
}
2320
2321
void AbstractMetaBuilder::decideUsagePattern(AbstractMetaType *metaType)
2322
{
2323
    metaType->decideUsagePattern();
2324
}
2325
2326
QString AbstractMetaBuilder::fixDefaultValue(ArgumentModelItem item, AbstractMetaType* type,
2327
                                                   AbstractMetaFunction* fnc, AbstractMetaClass* implementingClass,
2328
                                                   int argumentIndex)
2329
{
2330
    QString functionName = fnc->name();
2331
    QString className = implementingClass ? implementingClass->qualifiedCppName() : QString();
2332
2333
    QString expr = item->defaultValueExpression();
2334
    if (type) {
2335
        if (type->isPrimitive()) {
2336
            if (type->name() == "boolean") {
2337
                if (expr != "false" && expr != "true") {
2338
                    bool ok = false;
2339
                    int number = expr.toInt(&ok);
2340
                    if (ok && number)
2341
                        expr = "true";
2342
                    else
2343
                        expr = "false";
2344
                }
2345
            } else {
2346
                // This can be an enum or flag so I need to delay the
2347
                // translation untill all namespaces are completly
2348
                // processed. This is done in figureOutEnumValues()
2349
            }
2350
        } else if (type->isFlags() || type->isEnum()) {
2351
            bool isNumber;
2352
            expr.toInt(&isNumber);
2353
            if (!isNumber && expr.indexOf("::") < 0) {
2354
                // Add the enum/flag scope to default value, making it usable
2355
                // from other contexts beside its owner class hierarchy
2356
                QRegExp typeRegEx("[^<]*[<]([^:]*::).*");
2357
                typeRegEx.indexIn(type->minimalSignature());
2358
                expr = typeRegEx.cap(1) + expr;
2359
            }
2360
        } else if (type->isContainer() && expr.contains('<')) {
2361
            QRegExp typeRegEx("[^<]*<(.*)>");
2362
            typeRegEx.indexIn(type->minimalSignature());
2363
            QRegExp defaultRegEx("([^<]*<).*(>[^>]*)");
2364
            defaultRegEx.indexIn(expr);
2365
            expr = defaultRegEx.cap(1) + typeRegEx.cap(1) + defaultRegEx.cap(2);
2366
        } else {
2367
            // Here the default value is supposed to be a constructor,
2368
            // a class field, or a constructor receiving a class field
2369
            QRegExp defaultRegEx("([^\\(]*\\(|)([^\\)]*)(\\)|)");
2370
            defaultRegEx.indexIn(expr);
2371
2372
            QString defaultValueCtorName = defaultRegEx.cap(1);
2373
            if (defaultValueCtorName.endsWith('('))
2374
                defaultValueCtorName.chop(1);
2375
2376
            // Fix the scope for constructor using the already
2377
            // resolved argument type as a reference.
2378
            // The following regular expression extracts any
2379
            // use of namespaces/scopes from the type string.
2380
            QRegExp typeRegEx("^(?:const[\\s]+|)([\\w:]*::|)([A-Za-z_]\\w*)\\s*[&\\*]?$");
2381
            typeRegEx.indexIn(type->minimalSignature());
2382
2383
            QString typeNamespace = typeRegEx.cap(1);
2384
            QString typeCtorName = typeRegEx.cap(2);
2385
            if (!typeNamespace.isEmpty() && defaultValueCtorName == typeCtorName)
2386
                expr.prepend(typeNamespace);
2387
2388
            // Fix scope if the parameter is a field of the current class
2389
            if (implementingClass) {
2390
                foreach (const AbstractMetaField* field, implementingClass->fields()) {
2391
                    if (defaultRegEx.cap(2) == field->name()) {
2392
                        expr = defaultRegEx.cap(1) + implementingClass->name() + "::" + defaultRegEx.cap(2) + defaultRegEx.cap(3);
2393
                        break;
2394
                    }
2395
                }
2396
            }
2397
        }
2398
    } else {
2399
        QString warn = QString("undefined type for default value '%3' of argument in function '%1', class '%2'")
2400
                       .arg(functionName).arg(className).arg(item->defaultValueExpression());
2401
        ReportHandler::warning(warn);
2402
        expr = QString();
2403
    }
2404
2405
    return expr;
2406
}
2407
2408
bool AbstractMetaBuilder::isQObject(const QString& qualifiedName)
2409
{
2410
    if (qualifiedName == "QObject")
2411
        return true;
2412
2413
    ClassModelItem classItem = m_dom->findClass(qualifiedName);
2414
2415
    if (!classItem) {
2416
        QStringList names = qualifiedName.split(QLatin1String("::"));
2417
        NamespaceModelItem ns = model_dynamic_cast<NamespaceModelItem>(m_dom);
2418
        for (int i = 0; i < names.size() - 1 && ns; ++i)
2419
            ns = ns->namespaceMap().value(names.at(i));
2420
        if (ns && names.size() >= 2)
2421
            classItem = ns->findClass(names.at(names.size() - 1));
2422
    }
2423
2424
    bool isqobject = classItem && classItem->extendsClass("QObject");
2425
2426
    if (classItem && !isqobject) {
2427
        QStringList baseClasses = classItem->baseClasses();
2428
        for (int i = 0; i < baseClasses.count(); ++i) {
2429
2430
            isqobject = isQObject(baseClasses.at(i));
2431
            if (isqobject)
2432
                break;
2433
        }
2434
    }
2435
2436
    return isqobject;
2437
}
2438
2439
2440
bool AbstractMetaBuilder::isEnum(const QStringList& qualified_name)
2441
{
2442
    CodeModelItem item = m_dom->model()->findItem(qualified_name, m_dom->toItem());
2443
    return item && item->kind() == _EnumModelItem::__node_kind;
2444
}
2445
2446
AbstractMetaClassList AbstractMetaBuilder::getBaseClasses(const AbstractMetaClass* metaClass) const
2447
{
2448
    AbstractMetaClassList baseClasses;
2449
    foreach (const QString& parent, metaClass->baseClassNames()) {
2450
        AbstractMetaClass* cls = m_metaClasses.findClass(parent);
2451
        if (cls)
2452
            baseClasses << cls;
2453
    }
2454
    return baseClasses;
2455
}
2456
2457
bool AbstractMetaBuilder::ancestorHasPrivateCopyConstructor(const AbstractMetaClass* metaClass) const
2458
{
2459
    if (metaClass->hasPrivateCopyConstructor())
2460
        return true;
2461
    foreach (const AbstractMetaClass* cls, getBaseClasses(metaClass)) {
2462
        if (ancestorHasPrivateCopyConstructor(cls))
2463
            return true;
2464
    }
2465
    return false;
2466
}
2467
2468
AbstractMetaType* AbstractMetaBuilder::inheritTemplateType(const QList<AbstractMetaType*>& templateTypes,
2469
                                                           const AbstractMetaType* metaType, bool* ok)
2470
{
2471
    if (ok)
2472
        *ok = true;
2473
    if (!metaType || (!metaType->typeEntry()->isTemplateArgument() && !metaType->hasInstantiations()))
2474
        return metaType ? metaType->copy() : 0;
2475
2476
    AbstractMetaType *returned = metaType->copy();
2477
    returned->setOriginalTemplateType(metaType->copy());
2478
2479
    if (returned->typeEntry()->isTemplateArgument()) {
2480
        const TemplateArgumentEntry* tae = static_cast<const TemplateArgumentEntry*>(returned->typeEntry());
2481
2482
        // If the template is intantiated with void we special case this as rejecting the functions that use this
2483
        // parameter from the instantiation.
2484
        if (templateTypes.size() <= tae->ordinal() || templateTypes.at(tae->ordinal())->typeEntry()->name() == "void") {
2485
            if (ok)
2486
                *ok = false;
2487
            return 0;
2488
        }
2489
2490
        AbstractMetaType* t = returned->copy();
2491
        t->setTypeEntry(templateTypes.at(tae->ordinal())->typeEntry());
2492
        t->setIndirections(templateTypes.at(tae->ordinal())->indirections() + t->indirections() ? 1 : 0);
2493
        decideUsagePattern(t);
2494
2495
        delete returned;
2496
        returned = inheritTemplateType(templateTypes, t, ok);
2497
        if (ok && !(*ok))
2498
            return 0;
2499
    }
2500
2501
    if (returned->hasInstantiations()) {
2502
        AbstractMetaTypeList instantiations = returned->instantiations();
2503
        for (int i = 0; i < instantiations.count(); ++i) {
2504
            AbstractMetaType *type = instantiations[i];
2505
            instantiations[i] = inheritTemplateType(templateTypes, type, ok);
2506
            if (ok && !(*ok))
2507
                return 0;
2508
        }
2509
        returned->setInstantiations(instantiations, true);
2510
    }
2511
2512
    return returned;
2513
}
2514
2515
bool AbstractMetaBuilder::inheritTemplate(AbstractMetaClass* subclass,
2516
                                          const AbstractMetaClass* templateClass,
2517
                                          const TypeParser::Info& info)
2518
{
2519
    QList<TypeParser::Info> targs = info.template_instantiations;
2520
    QList<AbstractMetaType*> templateTypes;
2521
2522
    if (subclass->isTypeAlias()) {
2523
        subclass->setHasCloneOperator(templateClass->hasCloneOperator());
2524
        subclass->setHasEqualsOperator(templateClass->hasEqualsOperator());
2525
        subclass->setHasHashFunction(templateClass->hasHashFunction());
2526
        subclass->setHasNonPrivateConstructor(templateClass->hasNonPrivateConstructor());
2527
        subclass->setHasPrivateDestructor(templateClass->hasPrivateDestructor());
2528
        subclass->setHasProtectedDestructor(templateClass->hasProtectedDestructor());
2529
        subclass->setHasVirtualDestructor(templateClass->hasVirtualDestructor());
2530
    }
2531
2532
    foreach (const TypeParser::Info &i, targs) {
2533
        QString typeName = i.qualified_name.join("::");
2534
        QStringList possibleNames;
2535
        possibleNames << subclass->qualifiedCppName() + "::" + typeName;
2536
        possibleNames << templateClass->qualifiedCppName() + "::" + typeName;
2537
        if (subclass->enclosingClass())
2538
            possibleNames << subclass->enclosingClass()->qualifiedCppName() + "::" + typeName;
2539
        possibleNames << typeName;
2540
2541
        TypeDatabase* typeDb = TypeDatabase::instance();
2542
        TypeEntry* t = 0;
2543
        QString templateParamName;
2544
        foreach (QString possibleName, possibleNames) {
2545
            t = typeDb->findType(possibleName);
2546
            if (t) {
2547
                QString templateParamName = possibleName;
2548
                break;
2549
            }
2550
        }
2551
2552
        if (t) {
2553
            AbstractMetaType* temporaryType = createMetaType();
2554
            temporaryType->setTypeEntry(t);
2555
            temporaryType->setConstant(i.is_constant);
2556
            temporaryType->setReference(i.is_reference);
2557
            temporaryType->setIndirections(i.indirections);
2558
            temporaryType->decideUsagePattern();
2559
            templateTypes << temporaryType;
2560
        } else {
2561
            ReportHandler::warning("Ignoring template parameter " + templateParamName + " from " + info.instantiationName() + ", because I don't know what it is.");
2562
        }
2563
    }
2564
2565
    AbstractMetaFunctionList funcs = subclass->functions();
2566
    foreach (const AbstractMetaFunction* function, templateClass->functions()) {
2567
        if (function->isModifiedRemoved(TypeSystem::All))
2568
            continue;
2569
2570
        AbstractMetaFunction *f = function->copy();
2571
        f->setArguments(AbstractMetaArgumentList());
2572
2573
        bool ok = true;
2574
        AbstractMetaType *ftype = function->type();
2575
        f->replaceType(inheritTemplateType(templateTypes, ftype, &ok));
2576
        if (!ok) {
2577
            delete f;
2578
            continue;
2579
        }
2580
2581
        foreach (AbstractMetaArgument* argument, function->arguments()) {
2582
            AbstractMetaType* atype = argument->type();
2583
2584
            AbstractMetaArgument *arg = argument->copy();
2585
            arg->replaceType(inheritTemplateType(templateTypes, atype, &ok));
2586
            if (!ok)
2587
                break;
2588
            f->addArgument(arg);
2589
        }
2590
2591
        if (!ok) {
2592
            delete f;
2593
            continue;
2594
        }
2595
2596
        // There is no base class in the target language to inherit from here, so
2597
        // the template instantiation is the class that implements the function.
2598
        f->setImplementingClass(subclass);
2599
2600
        // We also set it as the declaring class, since the superclass is
2601
        // supposed to disappear. This allows us to make certain function modifications
2602
        // on the inherited functions.
2603
        f->setDeclaringClass(subclass);
2604
2605
2606
        if (f->isConstructor() && subclass->isTypeAlias()) {
2607
            f->setName(subclass->name());
2608
            f->setOriginalName(subclass->name());
2609
        } else if (f->isConstructor()) {
2610
            delete f;
2611
            continue;
2612
        }
2613
2614
        // if the instantiation has a function named the same as an existing
2615
        // function we have shadowing so we need to skip it.
2616
        bool found = false;
2617
        for (int i = 0; i < funcs.size(); ++i) {
2618
            if (funcs.at(i)->name() == f->name()) {
2619
                found = true;
2620
                continue;
2621
            }
2622
        }
2623
        if (found) {
2624
            delete f;
2625
            continue;
2626
        }
2627
2628
        ComplexTypeEntry* te = subclass->typeEntry();
2629
        FunctionModificationList mods = function->modifications(templateClass);
2630
        for (int i = 0; i < mods.size(); ++i) {
2631
            FunctionModification mod = mods.at(i);
2632
            mod.signature = f->minimalSignature();
2633
2634
            // If we ever need it... Below is the code to do
2635
            // substitution of the template instantation type inside
2636
            // injected code..
2637
#if 0
2638
            if (mod.modifiers & Modification::CodeInjection) {
2639
                for (int j = 0; j < template_types.size(); ++j) {
2640
                    CodeSnip &snip = mod.snips.last();
2641
                    QString code = snip.code();
2642
                    code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j),
2643
                                 template_types.at(j)->typeEntry()->qualifiedCppName());
2644
                    snip.codeList.clear();
2645
                    snip.addCode(code);
2646
                }
2647
            }
2648
#endif
2649
            te->addFunctionModification(mod);
2650
        }
2651
2652
        subclass->addFunction(f);
2653
    }
2654
2655
    subclass->setTemplateBaseClass(templateClass);
2656
    subclass->setTemplateBaseClassInstantiations(templateTypes);
2657
    subclass->setInterfaces(templateClass->interfaces());
2658
    subclass->setBaseClass(templateClass->baseClass());
2659
2660
    return true;
2661
}
2662
2663
void AbstractMetaBuilder::parseQ_Property(AbstractMetaClass* metaClass, const QStringList& declarations)
2664
{
2665
    for (int i = 0; i < declarations.size(); ++i) {
2666
        QString p = declarations.at(i);
2667
2668
        QStringList l = p.split(QLatin1String(" "));
2669
2670
2671
        QStringList qualifiedScopeName = currentScope()->qualifiedName();
2672
        bool ok = false;
2673
        AbstractMetaType* type = 0;
2674
        QString scope;
2675
        for (int j = qualifiedScopeName.size(); j >= 0; --j) {
2676
            scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join("::") + "::" : QString();
2677
            TypeInfo info;
2678
            info.setQualifiedName((scope + l.at(0)).split("::"));
2679
2680
            type = translateType(info, &ok);
2681
            if (type && ok)
2682
                break;
2683
        }
2684
2685
        if (!type || !ok) {
2686
            ReportHandler::warning(QString("Unable to decide type of property: '%1' in class '%2'")
2687
                                   .arg(l.at(0)).arg(metaClass->name()));
2688
            continue;
2689
        }
2690
2691
        QString typeName = scope + l.at(0);
2692
2693
        QPropertySpec* spec = new QPropertySpec(type->typeEntry());
2694
        spec->setName(l.at(1));
2695
        spec->setIndex(i);
2696
2697
        for (int pos = 2; pos + 1 < l.size(); pos += 2) {
2698
            if (l.at(pos) == QLatin1String("READ"))
2699
                spec->setRead(l.at(pos + 1));
2700
            else if (l.at(pos) == QLatin1String("WRITE"))
2701
                spec->setWrite(l.at(pos + 1));
2702
            else if (l.at(pos) == QLatin1String("DESIGNABLE"))
2703
                spec->setDesignable(l.at(pos + 1));
2704
            else if (l.at(pos) == QLatin1String("RESET"))
2705
                spec->setReset(l.at(pos + 1));
2706
        }
2707
2708
        metaClass->addPropertySpec(spec);
2709
        delete type;
2710
    }
2711
}
2712
2713
static AbstractMetaFunction* findCopyCtor(AbstractMetaClass* cls)
2714
{
2715
    AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::Invisible);
2716
    functions <<  cls->queryFunctions(AbstractMetaClass::Visible);
2717
2718
    foreach (AbstractMetaFunction* f, functions) {
2719
        if (f->isConstructor() || f->name() == "operator=") {
2720
            AbstractMetaArgumentList arguments = f->arguments();
2721
            if (arguments.size() == 1) {
2722
                if (cls->typeEntry()->qualifiedCppName() == arguments.at(0)->type()->typeEntry()->qualifiedCppName())
2723
                    return f;
2724
            }
2725
        }
2726
    }
2727
    return 0;
2728
}
2729
2730
void AbstractMetaBuilder::setupClonable(AbstractMetaClass* cls)
2731
{
2732
    bool result = true;
2733
2734
    // find copy ctor for the current class
2735
    AbstractMetaFunction* copyCtor = findCopyCtor(cls);
2736
    if (copyCtor) { // if exists a copy ctor in this class
2737
        result = copyCtor->isPublic();
2738
    } else { // else... lets find one in the parent class
2739
        QQueue<AbstractMetaClass*> baseClasses;
2740
        if (cls->baseClass())
2741
            baseClasses.enqueue(cls->baseClass());
2742
        baseClasses << cls->interfaces();
2743
2744
        while (!baseClasses.isEmpty()) {
2745
            AbstractMetaClass* currentClass = baseClasses.dequeue();
2746
            baseClasses << currentClass->interfaces();
2747
            if (currentClass->baseClass())
2748
                baseClasses.enqueue(currentClass->baseClass());
2749
2750
            copyCtor = findCopyCtor(currentClass);
2751
            if (copyCtor) {
2752
                result = copyCtor->isPublic();
2753
                break;
2754
            }
2755
        }
2756
    }
2757
    cls->setHasCloneOperator(result);
2758
}
2759
2760
void AbstractMetaBuilder::setupExternalConversion(AbstractMetaClass* cls) {
2761
    AbstractMetaFunctionList convOps = cls->operatorOverloads(AbstractMetaClass::ConversionOp);
2762
    foreach (AbstractMetaFunction* func, convOps) {
2763
        if (func->isModifiedRemoved())
2764
            continue;
2765
        AbstractMetaClass* metaClass = m_metaClasses.findClass(func->type()->typeEntry());
2766
        if (!metaClass)
2767
            continue;
2768
        metaClass->addExternalConversionOperator(func);
2769
    }
2770
    foreach (AbstractMetaClass* innerClass, cls->innerClasses())
2771
        setupExternalConversion(innerClass);
2772
}
2773
2774
static void writeRejectLogFile(const QString &name,
2775
                                  const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects)
2776
{
2777
    QFile f(name);
2778
    if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
2779
        ReportHandler::warning(QString("failed to write log file: '%1'")
2780
                               .arg(f.fileName()));
2781
        return;
2782
    }
2783
2784
    QTextStream s(&f);
2785
2786
2787
    for (int reason = 0; reason < AbstractMetaBuilder::NoReason; ++reason) {
2788
        s << QString(72, '*') << endl;
2789
        switch (reason) {
2790
        case AbstractMetaBuilder::NotInTypeSystem:
2791
            s << "Not in type system";
2792
            break;
2793
        case AbstractMetaBuilder::GenerationDisabled:
2794
            s << "Generation disabled by type system";
2795
            break;
2796
        case AbstractMetaBuilder::RedefinedToNotClass:
2797
            s << "Type redefined to not be a class";
2798
            break;
2799
2800
        case AbstractMetaBuilder::UnmatchedReturnType:
2801
            s << "Unmatched return type";
2802
            break;
2803
2804
        case AbstractMetaBuilder::UnmatchedArgumentType:
2805
            s << "Unmatched argument type";
2806
            break;
2807
2808
        case AbstractMetaBuilder::ApiIncompatible:
2809
            s << "Incompatible API";
2810
            break;
2811
2812
        default:
2813
            s << "unknown reason";
2814
            break;
2815
        }
2816
2817
        s << endl;
2818
2819
        for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin();
2820
             it != rejects.constEnd(); ++it) {
2821
            if (it.value() != reason)
2822
                continue;
2823
            s << " - " << it.key() << endl;
2824
        }
2825
2826
        s << QString(72, '*') << endl << endl;
2827
    }
2828
2829
}
2830
2831
2832
void AbstractMetaBuilder::dumpLog()
2833
{
2834
    writeRejectLogFile(m_logDirectory + "mjb_rejected_classes.log", m_rejectedClasses);
2835
    writeRejectLogFile(m_logDirectory + "mjb_rejected_enums.log", m_rejectedEnums);
2836
    writeRejectLogFile(m_logDirectory + "mjb_rejected_functions.log", m_rejectedFunctions);
2837
    writeRejectLogFile(m_logDirectory + "mjb_rejected_fields.log", m_rejectedFields);
2838
}
2839
2840
AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const AbstractMetaClass* cppClass) const
2841
{
2842
    QLinkedList<int> unmappedResult;
2843
    QHash<QString, int> map;
2844
    QHash<int, AbstractMetaClass*> reverseMap;
2845
2846
    const AbstractMetaClassList& classList = cppClass ? cppClass->innerClasses() : m_metaClasses;
2847
2848
    int i = 0;
2849
    foreach (AbstractMetaClass* clazz, classList) {
2850
        if (map.contains(clazz->qualifiedCppName()))
2851
            continue;
2852
        map[clazz->qualifiedCppName()] = i;
2853
        reverseMap[i] = clazz;
2854
        i++;
2855
    }
2856
2857
    Graph graph(map.count());
2858
2859
    // TODO choose a better name to these regexs
2860
    QRegExp regex1("\\(.*\\)");
2861
    QRegExp regex2("::.*");
2862
    foreach (AbstractMetaClass* clazz, classList) {
2863
        if (clazz->isInterface() || !clazz->typeEntry()->generateCode())
2864
            continue;
2865
2866
        if (clazz->enclosingClass() && map.contains(clazz->enclosingClass()->qualifiedCppName()))
2867
            graph.addEdge(map[clazz->enclosingClass()->qualifiedCppName()], map[clazz->qualifiedCppName()]);
2868
2869
        AbstractMetaClassList bases = getBaseClasses(clazz);
2870
        foreach(AbstractMetaClass* baseClass, bases) {
2871
            // Fix polymorphic expression
2872
            if (clazz->baseClass() == baseClass)
2873
                clazz->setBaseClass(baseClass);
2874
2875
            if (map.contains(baseClass->qualifiedCppName()))
2876
                graph.addEdge(map[baseClass->qualifiedCppName()], map[clazz->qualifiedCppName()]);
2877
        }
2878
2879
        foreach (AbstractMetaFunction* func, clazz->functions()) {
2880
            foreach (AbstractMetaArgument* arg, func->arguments()) {
2881
                // check methods with default args
2882
                QString defaultExpression = arg->originalDefaultValueExpression();
2883
                if (!defaultExpression.isEmpty()) {
2884
                    if ((defaultExpression == "0") && (arg->type()->isValue()))
2885
                        defaultExpression = arg->type()->name();
2886
2887
                    defaultExpression.replace(regex1, "");
2888
                    defaultExpression.replace(regex2, "");
2889
                }
2890
                if (!defaultExpression.isEmpty()) {
2891
                    QString exprClassName = clazz->qualifiedCppName() + "::" + defaultExpression;
2892
                    if (!map.contains(exprClassName)) {
2893
                        bool found = false;
2894
                        foreach(AbstractMetaClass* baseClass, bases) {
2895
                            exprClassName = baseClass->qualifiedCppName() + "::" + defaultExpression;
2896
                            if (map.contains(exprClassName)) {
2897
                                found = true;
2898
                                break;
2899
                            }
2900
                        }
2901
                        if (!found) {
2902
                            if (map.contains(defaultExpression))
2903
                                exprClassName = defaultExpression;
2904
                            else
2905
                                exprClassName.clear();
2906
                        }
2907
                    }
2908
                    if (!exprClassName.isEmpty() && exprClassName != clazz->qualifiedCppName())
2909
                        graph.addEdge(map[exprClassName], map[clazz->qualifiedCppName()]);
2910
                }
2911
            }
2912
        }
2913
    }
2914
2915
    AbstractMetaClassList result;
2916
    unmappedResult = graph.topologicalSort();
2917
    if (unmappedResult.isEmpty() && graph.nodeCount()) {
2918
        QTemporaryFile tempFile;
2919
        tempFile.setAutoRemove(false);
2920
        tempFile.open();
2921
        QHash<int, QString> hash;
2922
        QHash<QString, int>::iterator it = map.begin();
2923
        for (; it != map.end(); ++it)
2924
            hash[it.value()] = it.key();
2925
        graph.dumpDot(hash, tempFile.fileName());
2926
        ReportHandler::warning("Cyclic dependency found! Graph can be found at "+tempFile.fileName());
2927
    } else {
2928
        foreach (int i, unmappedResult) {
2929
            Q_ASSERT(reverseMap.contains(i));
2930
            if (!reverseMap[i]->isInterface())
2931
                result << reverseMap[i];
2932
        }
2933
    }
2934
2935
    return result;
2936
}
2937
2938
AbstractMetaArgumentList AbstractMetaBuilder::reverseList(const AbstractMetaArgumentList& list)
2939
{
2940
    AbstractMetaArgumentList ret;
2941
2942
    int index = list.size();
2943
    foreach (AbstractMetaArgument* arg, list) {
2944
        arg->setArgumentIndex(index);
2945
        ret.prepend(arg);
2946
        index--;
2947
    }
2948
2949
    return ret;
2950
}
2951
2952
void AbstractMetaBuilder::setGlobalHeader(const QString& globalHeader)
2953
{
2954
    m_globalHeader = QFileInfo(globalHeader);
2955
}
2956
2957
void AbstractMetaBuilder::setInclude(TypeEntry* te, const QString& fileName) const
2958
{
2959
    QFileInfo info(fileName);
2960
    if (m_globalHeader.fileName() != info.fileName())
2961
        te->setInclude(Include(Include::IncludePath, info.fileName()));
2962
}