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 "generator.h"
25
#include "reporthandler.h"
26
#include "fileout.h"
27
#include "apiextractor.h"
28
29
#include <QtCore/QDir>
30
#include <QtCore/QFile>
31
#include <QtCore/QFileInfo>
32
#include <QDebug>
33
#include <typedatabase.h>
34
35
struct Generator::GeneratorPrivate {
36
    const ApiExtractor* apiextractor;
37
    QString outDir;
38
    // License comment
39
    QString licenseComment;
40
    QString packageName;
41
    int numGenerated;
42
    int numGeneratedWritten;
43
    QStringList instantiatedContainersNames;
44
    QList<const AbstractMetaType*> instantiatedContainers;
45
};
46
47
Generator::Generator() : m_d(new GeneratorPrivate)
48
{
49
    m_d->numGenerated = 0;
50
    m_d->numGeneratedWritten = 0;
51
    m_d->instantiatedContainers = QList<const AbstractMetaType*>();
52
    m_d->instantiatedContainersNames = QStringList();
53
}
54
55
Generator::~Generator()
56
{
57
    delete m_d;
58
}
59
60
bool Generator::setup(const ApiExtractor& extractor, const QMap< QString, QString > args)
61
{
62
    m_d->apiextractor = &extractor;
63
    TypeEntryHash allEntries = TypeDatabase::instance()->allEntries();
64
    TypeEntry* entryFound = 0;
65
    foreach (QList<TypeEntry*> entryList, allEntries.values()) {
66
        foreach (TypeEntry* entry, entryList) {
67
            if (entry->type() == TypeEntry::TypeSystemType && entry->generateCode()) {
68
                entryFound = entry;
69
                break;
70
            }
71
        }
72
        if (entryFound)
73
            break;
74
    }
75
    if (entryFound)
76
        m_d->packageName = entryFound->name();
77
    else
78
        ReportHandler::warning("Couldn't find the package name!!");
79
80
    collectInstantiatedContainers();
81
82
    return doSetup(args);
83
}
84
85
QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType* type)
86
{
87
    if (!type->typeEntry()->isContainer())
88
        return type->cppSignature();
89
    QString typeName = type->cppSignature();
90
    if (type->isConstant())
91
        typeName.remove(0, sizeof("const ") / sizeof(char) - 1);
92
    if (type->isReference())
93
        typeName.chop(1);
94
    while (typeName.endsWith('*') || typeName.endsWith(' '))
95
        typeName.chop(1);
96
    return typeName;
97
}
98
99
void Generator::addInstantiatedContainers(const AbstractMetaType* type)
100
{
101
    if (!type)
102
        return;
103
    foreach (const AbstractMetaType* t, type->instantiations())
104
        addInstantiatedContainers(t);
105
    if (!type->typeEntry()->isContainer())
106
        return;
107
    QString typeName = getSimplifiedContainerTypeName(type);
108
    if (!m_d->instantiatedContainersNames.contains(typeName)) {
109
        m_d->instantiatedContainersNames.append(typeName);
110
        m_d->instantiatedContainers.append(type);
111
    }
112
}
113
114
void Generator::collectInstantiatedContainers(const AbstractMetaFunction* func)
115
{
116
    addInstantiatedContainers(func->type());
117
    foreach (const AbstractMetaArgument* arg, func->arguments())
118
        addInstantiatedContainers(arg->type());
119
}
120
121
void Generator::collectInstantiatedContainers(const AbstractMetaClass* metaClass)
122
{
123
    if (!metaClass->typeEntry()->generateCode())
124
        return;
125
    foreach (const AbstractMetaFunction* func, metaClass->functions())
126
        collectInstantiatedContainers(func);
127
    foreach (const AbstractMetaField* field, metaClass->fields())
128
        addInstantiatedContainers(field->type());
129
    foreach (AbstractMetaClass* innerClass, metaClass->innerClasses())
130
        collectInstantiatedContainers(innerClass);
131
}
132
133
void Generator::collectInstantiatedContainers()
134
{
135
    foreach (const AbstractMetaFunction* func, globalFunctions())
136
        collectInstantiatedContainers(func);
137
    foreach (const AbstractMetaClass* metaClass, classes())
138
        collectInstantiatedContainers(metaClass);
139
}
140
141
QList<const AbstractMetaType*> Generator::instantiatedContainers() const
142
{
143
    return m_d->instantiatedContainers;
144
}
145
146
QMap< QString, QString > Generator::options() const
147
{
148
    return QMap<QString, QString>();
149
}
150
151
AbstractMetaClassList Generator::classes() const
152
{
153
    return m_d->apiextractor->classes();
154
}
155
156
AbstractMetaFunctionList Generator::globalFunctions() const
157
{
158
    return m_d->apiextractor->globalFunctions();
159
}
160
161
AbstractMetaEnumList Generator::globalEnums() const
162
{
163
    return m_d->apiextractor->globalEnums();
164
}
165
166
QList<const PrimitiveTypeEntry*> Generator::primitiveTypes() const
167
{
168
    return m_d->apiextractor->primitiveTypes();
169
}
170
171
QList<const ContainerTypeEntry*> Generator::containerTypes() const
172
{
173
    return m_d->apiextractor->containerTypes();
174
}
175
176
const AbstractMetaEnum* Generator::findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const
177
{
178
    return m_d->apiextractor->findAbstractMetaEnum(typeEntry);
179
}
180
181
const AbstractMetaEnum* Generator::findAbstractMetaEnum(const TypeEntry* typeEntry) const
182
{
183
    return m_d->apiextractor->findAbstractMetaEnum(typeEntry);
184
}
185
186
const AbstractMetaEnum* Generator::findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const
187
{
188
    return m_d->apiextractor->findAbstractMetaEnum(typeEntry);
189
}
190
191
const AbstractMetaEnum* Generator::findAbstractMetaEnum(const AbstractMetaType* metaType) const
192
{
193
    return m_d->apiextractor->findAbstractMetaEnum(metaType);
194
}
195
196
QSet< QString > Generator::qtMetaTypeDeclaredTypeNames() const
197
{
198
    return m_d->apiextractor->qtMetaTypeDeclaredTypeNames();
199
}
200
201
QString Generator::licenseComment() const
202
{
203
    return m_d->licenseComment;
204
}
205
206
void Generator::setLicenseComment(const QString& licenseComment)
207
{
208
    m_d->licenseComment = licenseComment;
209
}
210
211
QString Generator::packageName() const
212
{
213
    return m_d->packageName;
214
}
215
216
QString Generator::moduleName() const
217
{
218
    QString& pkgName = m_d->packageName;
219
    return QString(pkgName).remove(0, pkgName.lastIndexOf('.') + 1);
220
}
221
222
QString Generator::outputDirectory() const
223
{
224
    return m_d->outDir;
225
}
226
227
void Generator::setOutputDirectory(const QString &outDir)
228
{
229
    m_d->outDir = outDir;
230
}
231
232
int Generator::numGenerated() const
233
{
234
    return m_d->numGenerated;
235
}
236
237
int Generator::numGeneratedAndWritten() const
238
{
239
    return m_d->numGeneratedWritten;
240
}
241
242
void Generator::generate()
243
{
244
    foreach (AbstractMetaClass *cls, m_d->apiextractor->classes()) {
245
        if (!shouldGenerate(cls))
246
            continue;
247
248
        QString fileName = fileNameForClass(cls);
249
        if (fileName.isNull())
250
            continue;
251
        ReportHandler::debugSparse(QString("generating: %1").arg(fileName));
252
253
        FileOut fileOut(outputDirectory() + '/' + subDirectoryForClass(cls) + '/' + fileName);
254
        generateClass(fileOut.stream, cls);
255
256
        if (fileOut.done())
257
            ++m_d->numGeneratedWritten;
258
        ++m_d->numGenerated;
259
    }
260
    finishGeneration();
261
}
262
263
bool Generator::shouldGenerateTypeEntry(const TypeEntry* type) const
264
{
265
    return type->codeGeneration() & TypeEntry::GenerateTargetLang;
266
}
267
268
bool Generator::shouldGenerate(const AbstractMetaClass* metaClass) const
269
{
270
    return shouldGenerateTypeEntry(metaClass->typeEntry());
271
}
272
273
void verifyDirectoryFor(const QFile &file)
274
{
275
    QDir dir = QFileInfo(file).dir();
276
    if (!dir.exists()) {
277
        if (!dir.mkpath(dir.absolutePath()))
278
            ReportHandler::warning(QString("unable to create directory '%1'")
279
                                   .arg(dir.absolutePath()));
280
    }
281
}
282
283
void Generator::replaceTemplateVariables(QString &code, const AbstractMetaFunction *func)
284
{
285
    const AbstractMetaClass *cpp_class = func->ownerClass();
286
    if (cpp_class)
287
        code.replace("%TYPE", cpp_class->name());
288
289
    foreach (AbstractMetaArgument *arg, func->arguments())
290
        code.replace("%" + QString::number(arg->argumentIndex() + 1), arg->name());
291
292
    //template values
293
    code.replace("%RETURN_TYPE", translateType(func->type(), cpp_class));
294
    code.replace("%FUNCTION_NAME", func->originalName());
295
296
    if (code.contains("%ARGUMENT_NAMES")) {
297
        QString str;
298
        QTextStream aux_stream(&str);
299
        writeArgumentNames(aux_stream, func, Generator::SkipRemovedArguments);
300
        code.replace("%ARGUMENT_NAMES", str);
301
    }
302
303
    if (code.contains("%ARGUMENTS")) {
304
        QString str;
305
        QTextStream aux_stream(&str);
306
        writeFunctionArguments(aux_stream, func, Options(SkipDefaultValues) | SkipRemovedArguments);
307
        code.replace("%ARGUMENTS", str);
308
    }
309
}
310
311
QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor)
312
{
313
    // detect number of spaces before the first character
314
    QStringList lst(code.split("\n"));
315
    QRegExp nonSpaceRegex("[^\\s]");
316
    int spacesToRemove = 0;
317
    foreach(QString line, lst) {
318
        if (!line.trimmed().isEmpty()) {
319
            spacesToRemove = line.indexOf(nonSpaceRegex);
320
            if (spacesToRemove == -1)
321
                spacesToRemove = 0;
322
            break;
323
        }
324
    }
325
326
    static QRegExp emptyLine("\\s*[\\r]?[\\n]?\\s*");
327
328
    foreach(QString line, lst) {
329
        if (!line.isEmpty() && !emptyLine.exactMatch(line)) {
330
            while (line.end()->isSpace())
331
                line.chop(1);
332
            int limit = 0;
333
            for(int i = 0; i < spacesToRemove; ++i) {
334
                if (!line[i].isSpace())
335
                    break;
336
                limit++;
337
            }
338
339
            s << indentor << line.remove(0, limit);
340
        }
341
        s << endl;
342
    }
343
    return s;
344
}
345
346
AbstractMetaFunctionList Generator::implicitConversions(const TypeEntry* type) const
347
{
348
    if (type->isValue()) {
349
        const AbstractMetaClass* metaClass = classes().findClass(type);
350
        if (metaClass)
351
            return metaClass->implicitConversions();
352
    }
353
    return AbstractMetaFunctionList();
354
}
355
356
AbstractMetaFunctionList Generator::implicitConversions(const AbstractMetaType* metaType) const
357
{
358
    return implicitConversions(metaType->typeEntry());
359
}
360
361
bool Generator::isObjectType(const TypeEntry* type)
362
{
363
    if (type->isComplex())
364
        return Generator::isObjectType((const ComplexTypeEntry*)type);
365
    return type->isObject();
366
}
367
bool Generator::isObjectType(const ComplexTypeEntry* type)
368
{
369
    return type->isObject() || type->isQObject();
370
}
371
bool Generator::isObjectType(const AbstractMetaClass* metaClass)
372
{
373
    return Generator::isObjectType(metaClass->typeEntry());
374
}
375
bool Generator::isObjectType(const AbstractMetaType* metaType)
376
{
377
    return isObjectType(metaType->typeEntry());
378
}
379
380
bool Generator::isPointer(const AbstractMetaType* type)
381
{
382
    return type->indirections() > 0
383
            || type->isNativePointer()
384
            || type->isValuePointer();
385
}
386
387
bool Generator::isCString(const AbstractMetaType* type)
388
{
389
    return type->isNativePointer()
390
            && type->indirections() == 1
391
            && type->name() == "char";
392
}
393
394
bool Generator::isVoidPointer(const AbstractMetaType* type)
395
{
396
    return type->isNativePointer()
397
            && type->indirections() == 1
398
            && type->name() == "void";
399
}
400
401
QString Generator::getFullTypeName(const TypeEntry* type) const
402
{
403
    return QString("%1%2").arg(type->isCppPrimitive() ? "" : "::").arg(type->qualifiedCppName());
404
}
405
406
QString Generator::getFullTypeName(const AbstractMetaType* type) const
407
{
408
    if (isCString(type))
409
        return "const char*";
410
    if (isVoidPointer(type))
411
        return "void*";
412
    if (type->typeEntry()->isContainer())
413
        return QString("::%1").arg(type->cppSignature());
414
    QString typeName;
415
    if (type->typeEntry()->isComplex() && type->hasInstantiations())
416
        typeName = getFullTypeNameWithoutModifiers(type);
417
    else
418
        typeName = getFullTypeName(type->typeEntry());
419
    return typeName + QString("*").repeated(type->indirections());
420
}
421
422
QString Generator::getFullTypeName(const AbstractMetaClass* metaClass) const
423
{
424
    return QString("::%1").arg(metaClass->qualifiedCppName());
425
}
426
427
QString Generator::getFullTypeNameWithoutModifiers(const AbstractMetaType* type) const
428
{
429
    if (isCString(type))
430
        return "const char*";
431
    if (isVoidPointer(type))
432
        return "void*";
433
    if (!type->hasInstantiations())
434
        return getFullTypeName(type->typeEntry());
435
    QString typeName = type->cppSignature();
436
    if (type->isConstant())
437
        typeName.remove(0, sizeof("const ") / sizeof(char) - 1);
438
    if (type->isReference())
439
        typeName.chop(1);
440
    while (typeName.endsWith('*') || typeName.endsWith(' '))
441
        typeName.chop(1);
442
    return QString("::%1").arg(typeName);
443
}
444
445
QString Generator::minimalConstructor(const AbstractMetaType* type) const
446
{
447
    if (!type || (type->isReference() && Generator::isObjectType(type)))
448
        return QString();
449
450
    if (type->isContainer()) {
451
        QString ctor = type->cppSignature();
452
        if (ctor.endsWith("*"))
453
            return QString("0");
454
        if (ctor.startsWith("const "))
455
            ctor.remove(0, sizeof("const ") / sizeof(char) - 1);
456
        if (ctor.endsWith("&")) {
457
            ctor.chop(1);
458
            ctor = ctor.trimmed();
459
        }
460
        return QString("::%1()").arg(ctor);
461
    }
462
463
    if (type->isNativePointer())
464
        return QString("((%1*)0)").arg(type->typeEntry()->qualifiedCppName());
465
466
    if (Generator::isPointer(type))
467
        return QString("((::%1*)0)").arg(type->typeEntry()->qualifiedCppName());
468
469
    if (type->typeEntry()->isComplex()) {
470
        const ComplexTypeEntry* cType = reinterpret_cast<const ComplexTypeEntry*>(type->typeEntry());
471
        QString ctor = cType->defaultConstructor();
472
        if (!ctor.isEmpty())
473
            return ctor;
474
        ctor = minimalConstructor(classes().findClass(cType));
475
        if (type->hasInstantiations())
476
            ctor = ctor.replace(getFullTypeName(cType), getFullTypeNameWithoutModifiers(type));
477
        return ctor;
478
    }
479
480
    return minimalConstructor(type->typeEntry());
481
}
482
483
QString Generator::minimalConstructor(const TypeEntry* type) const
484
{
485
    if (!type)
486
        return QString();
487
488
    if (type->isCppPrimitive())
489
        return QString("((%1)0)").arg(type->qualifiedCppName());
490
491
    if (type->isEnum() || type->isFlags())
492
        return QString("((::%1)0)").arg(type->qualifiedCppName());
493
494
    if (type->isPrimitive()) {
495
        QString ctor = reinterpret_cast<const PrimitiveTypeEntry*>(type)->defaultConstructor();
496
        // If a non-C++ (i.e. defined by the user) primitive type does not have
497
        // a default constructor defined by the user, the empty constructor is
498
        // heuristically returned. If this is wrong the build of the generated
499
        // bindings will tell.
500
        return (ctor.isEmpty()) ? QString("::%1()").arg(type->qualifiedCppName()) : ctor;
501
    }
502
503
    if (type->isComplex())
504
        return minimalConstructor(classes().findClass(type));
505
506
    return QString();
507
}
508
509
QString Generator::minimalConstructor(const AbstractMetaClass* metaClass) const
510
{
511
    if (!metaClass)
512
        return QString();
513
514
    const ComplexTypeEntry* cType = reinterpret_cast<const ComplexTypeEntry*>(metaClass->typeEntry());
515
    if (cType->hasDefaultConstructor())
516
        return cType->defaultConstructor();
517
518
    AbstractMetaFunctionList constructors = metaClass->queryFunctions(AbstractMetaClass::Constructors);
519
    int maxArgs = 0;
520
    foreach (const AbstractMetaFunction* ctor, constructors) {
521
        if (ctor->isUserAdded() || ctor->isPrivate() || ctor->isCopyConstructor())
522
            continue;
523
        int numArgs = ctor->arguments().size();
524
        if (numArgs == 0) {
525
            maxArgs = 0;
526
            break;
527
        }
528
        if (numArgs > maxArgs)
529
            maxArgs = numArgs;
530
    }
531
532
    QString qualifiedCppName = metaClass->typeEntry()->qualifiedCppName();
533
    QStringList templateTypes;
534
    foreach (TypeEntry* templateType, metaClass->templateArguments())
535
        templateTypes << templateType->qualifiedCppName();
536
    QString fixedTypeName = QString("%1<%2 >").arg(qualifiedCppName).arg(templateTypes.join(", "));
537
538
    // Empty constructor.
539
    if (maxArgs == 0)
540
        return QString("::%1()").arg(qualifiedCppName);
541
542
    QList<const AbstractMetaFunction*> candidates;
543
544
    // Constructors with C++ primitive types, enums or pointers only.
545
    // Start with the ones with fewer arguments.
546
    for (int i = 1; i <= maxArgs; ++i) {
547
        foreach (const AbstractMetaFunction* ctor, constructors) {
548
            if (ctor->isUserAdded() || ctor->isPrivate() || ctor->isCopyConstructor())
549
                continue;
550
551
            AbstractMetaArgumentList arguments = ctor->arguments();
552
            if (arguments.size() != i)
553
                continue;
554
555
            QStringList args;
556
            foreach (const AbstractMetaArgument* arg, arguments) {
557
                const TypeEntry* type = arg->type()->typeEntry();
558
                if (type == metaClass->typeEntry()) {
559
                    args.clear();
560
                    break;
561
                }
562
563
                if (!arg->originalDefaultValueExpression().isEmpty()) {
564
                    if (!arg->defaultValueExpression().isEmpty()
565
                        && arg->defaultValueExpression() != arg->originalDefaultValueExpression()) {
566
                        args << arg->defaultValueExpression();
567
                    }
568
                    break;
569
                }
570
571
                if (type->isCppPrimitive() || type->isEnum() || isPointer(arg->type())) {
572
                    QString argValue = minimalConstructor(arg->type());
573
                    if (argValue.isEmpty()) {
574
                        args.clear();
575
                        break;
576
                    }
577
                    args << argValue;
578
                } else {
579
                    args.clear();
580
                    break;
581
                }
582
            }
583
584
            if (!args.isEmpty())
585
                return QString("::%1(%2)").arg(qualifiedCppName).arg(args.join(", "));
586
587
            candidates << ctor;
588
        }
589
    }
590
591
    // Constructors with C++ primitive types, enums, pointers, value types,
592
    // and user defined primitive types.
593
    // Builds the minimal constructor recursively.
594
    foreach (const AbstractMetaFunction* ctor, candidates) {
595
        QStringList args;
596
        foreach (const AbstractMetaArgument* arg, ctor->arguments()) {
597
            if (arg->type()->typeEntry() == metaClass->typeEntry()) {
598
                args.clear();
599
                break;
600
            }
601
            QString argValue = minimalConstructor(arg->type());
602
            if (argValue.isEmpty()) {
603
                args.clear();
604
                break;
605
            }
606
            args << argValue;
607
        }
608
        if (!args.isEmpty()) {
609
            return QString("::%1(%2)").arg(qualifiedCppName)
610
                                      .arg(args.join(", "));
611
        }
612
    }
613
614
    return QString();
615
}
616
617
QString Generator::translateType(const AbstractMetaType *cType,
618
                                 const AbstractMetaClass *context,
619
                                 Options options) const
620
{
621
    QString s;
622
    static int constLen = strlen("const");
623
624
    if (context && cType &&
625
        context->typeEntry()->isGenericClass() &&
626
        cType->originalTemplateType()) {
627
        cType = cType->originalTemplateType();
628
    }
629
630
    if (!cType) {
631
        s = "void";
632
    } else if (cType->isArray()) {
633
        s = translateType(cType->arrayElementType(), context, options) + "[]";
634
    } else if (options & Generator::EnumAsInts && (cType->isEnum() || cType->isFlags())) {
635
        s = "int";
636
    } else {
637
        if (options & Generator::OriginalName) {
638
            s = cType->originalTypeDescription().trimmed();
639
            if ((options & Generator::ExcludeReference) && s.endsWith("&"))
640
                s = s.left(s.size()-1);
641
642
            // remove only the last const (avoid remove template const)
643
            if (options & Generator::ExcludeConst) {
644
                int index = s.lastIndexOf("const");
645
646
                if (index >= (s.size() - (constLen + 1))) // (VarType const)  or (VarType const[*|&])
647
                    s = s.remove(index, constLen);
648
            }
649
        } else if (options & Generator::ExcludeConst || options & Generator::ExcludeReference) {
650
            AbstractMetaType* copyType = cType->copy();
651
652
            if (options & Generator::ExcludeConst)
653
                copyType->setConstant(false);
654
655
            if (options & Generator::ExcludeReference)
656
                copyType->setReference(false);
657
658
            s = copyType->cppSignature();
659
            if (!copyType->typeEntry()->isVoid() && !copyType->typeEntry()->isCppPrimitive())
660
                s.prepend("::");
661
            delete copyType;
662
        } else {
663
            s = cType->cppSignature();
664
        }
665
    }
666
667
    return s;
668
}
669
670
671
QString Generator::subDirectoryForClass(const AbstractMetaClass* clazz) const
672
{
673
    return subDirectoryForPackage(clazz->package());
674
}
675
676
QString Generator::subDirectoryForPackage(QString packageName) const
677
{
678
    if (packageName.isEmpty())
679
        packageName = m_d->packageName;
680
    return QString(packageName).replace(".", QDir::separator());
681
}
682
683
template<typename T>
684
static QString getClassTargetFullName_(const T* t, bool includePackageName)
685
{
686
    QString name = t->name();
687
    const AbstractMetaClass* context = t->enclosingClass();
688
    while (context) {
689
        name.prepend('.');
690
        name.prepend(context->name());
691
        context = context->enclosingClass();
692
    }
693
    if (includePackageName) {
694
        name.prepend('.');
695
        name.prepend(t->package());
696
    }
697
    return name;
698
}
699
700
QString getClassTargetFullName(const AbstractMetaClass* metaClass, bool includePackageName)
701
{
702
    return getClassTargetFullName_(metaClass, includePackageName);
703
}
704
705
QString getClassTargetFullName(const AbstractMetaEnum* metaEnum, bool includePackageName)
706
{
707
    return getClassTargetFullName_(metaEnum, includePackageName);
708
}