mirror of
https://github.com/clementine-player/Clementine
synced 2024-12-17 20:09:50 +01:00
1987 lines
64 KiB
C++
1987 lines
64 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
** All rights reserved.
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
**
|
|
** This file is part of the Qt Script Generator project on Qt Labs.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** No Commercial Usage
|
|
** This file contains pre-release code and may not be distributed.
|
|
** You may use this file in accordance with the terms and conditions
|
|
** contained in the Technology Preview License Agreement accompanying
|
|
** this package.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 2.1 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** If you have questions regarding the use of this file, please contact
|
|
** Nokia at qt-info@nokia.com.
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "abstractmetalang.h"
|
|
#include "reporthandler.h"
|
|
|
|
/*******************************************************************************
|
|
* AbstractMetaType
|
|
*/
|
|
AbstractMetaType *AbstractMetaType::copy() const
|
|
{
|
|
AbstractMetaType *cpy = new AbstractMetaType;
|
|
|
|
cpy->setTypeUsagePattern(typeUsagePattern());
|
|
cpy->setConstant(isConstant());
|
|
cpy->setReference(isReference());
|
|
cpy->setIndirections(indirections());
|
|
cpy->setInstantiations(instantiations());
|
|
cpy->setArrayElementCount(arrayElementCount());
|
|
cpy->setOriginalTypeDescription(originalTypeDescription());
|
|
cpy->setOriginalTemplateType(originalTemplateType() ? originalTemplateType()->copy() : 0);
|
|
|
|
cpy->setArrayElementType(arrayElementType() ? arrayElementType()->copy() : 0);
|
|
|
|
cpy->setTypeEntry(typeEntry());
|
|
|
|
return cpy;
|
|
}
|
|
|
|
QString AbstractMetaType::cppSignature() const
|
|
{
|
|
QString s;
|
|
|
|
if (isConstant())
|
|
s += "const ";
|
|
|
|
s += typeEntry()->qualifiedCppName();
|
|
|
|
if (hasInstantiationInCpp()) {
|
|
QList<AbstractMetaType *> types = instantiations();
|
|
s += "<";
|
|
for (int i=0; i<types.count(); ++i) {
|
|
if (i > 0)
|
|
s += ", ";
|
|
s += types.at(i)->cppSignature();
|
|
}
|
|
s += " >";
|
|
}
|
|
|
|
if (actualIndirections()) {
|
|
s += ' ';
|
|
if (indirections())
|
|
s += QString(indirections(), '*');
|
|
if (isReference())
|
|
s += '&';
|
|
}
|
|
return s;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* AbstractMetaArgument
|
|
*/
|
|
AbstractMetaArgument *AbstractMetaArgument::copy() const
|
|
{
|
|
AbstractMetaArgument *cpy = new AbstractMetaArgument;
|
|
cpy->setName(AbstractMetaVariable::name());
|
|
cpy->setDefaultValueExpression(defaultValueExpression());
|
|
cpy->setType(type()->copy());
|
|
cpy->setArgumentIndex(argumentIndex());
|
|
|
|
return cpy;
|
|
}
|
|
|
|
|
|
QString AbstractMetaArgument::argumentName() const
|
|
{
|
|
QString n = AbstractMetaVariable::name();
|
|
if (n.isEmpty()) {
|
|
return QString("arg__%2").arg(m_argument_index + 1);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
|
|
QString AbstractMetaArgument::indexedName() const
|
|
{
|
|
QString n = AbstractMetaVariable::name();
|
|
if (n.isEmpty())
|
|
return argumentName();
|
|
return QString("%1%2").arg(n).arg(m_argument_index);
|
|
}
|
|
|
|
QString AbstractMetaArgument::name() const
|
|
{
|
|
Q_ASSERT_X(0, "AbstractMetaArgument::name()", "use argumentName() or indexedName() instead");
|
|
return QString();
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* AbstractMetaFunction
|
|
*/
|
|
AbstractMetaFunction::~AbstractMetaFunction()
|
|
{
|
|
qDeleteAll(m_arguments);
|
|
delete m_type;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Indicates that this function has a modification that removes it
|
|
*/
|
|
bool AbstractMetaFunction::isModifiedRemoved(int types) const
|
|
{
|
|
FunctionModificationList mods = modifications(implementingClass());
|
|
foreach (FunctionModification mod, mods) {
|
|
if (!mod.isRemoveModifier())
|
|
continue;
|
|
|
|
if ((mod.removal & types) == types)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool AbstractMetaFunction::needsCallThrough() const
|
|
{
|
|
if (ownerClass()->isInterface())
|
|
return false;
|
|
if (referenceCounts(implementingClass()).size() > 0)
|
|
return true;
|
|
if (argumentsHaveNativeId() || !isStatic())
|
|
return true;
|
|
|
|
foreach (const AbstractMetaArgument *arg, arguments()) {
|
|
if (arg->type()->isArray() || arg->type()->isTargetLangEnum() || arg->type()->isTargetLangFlags())
|
|
return true;
|
|
}
|
|
|
|
if (type() && (type()->isArray() || type()->isTargetLangEnum() || type()->isTargetLangFlags()))
|
|
return true;
|
|
|
|
for (int i=-1; i<=arguments().size(); ++i) {
|
|
TypeSystem::Ownership owner = this->ownership(implementingClass(), TypeSystem::TargetLangCode, i);
|
|
if (owner != TypeSystem::InvalidOwnership)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool AbstractMetaFunction::needsSuppressUncheckedWarning() const
|
|
{
|
|
for (int i=-1; i<=arguments().size(); ++i) {
|
|
QList<ReferenceCount> referenceCounts = this->referenceCounts(implementingClass(), i);
|
|
foreach (ReferenceCount referenceCount, referenceCounts) {
|
|
if (referenceCount.action != ReferenceCount::Set)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
QString AbstractMetaFunction::marshalledName() const
|
|
{
|
|
QString returned = "__qt_" + name();
|
|
AbstractMetaArgumentList arguments = this->arguments();
|
|
foreach (const AbstractMetaArgument *arg, arguments) {
|
|
returned += "_";
|
|
if (arg->type()->isNativePointer()) {
|
|
returned += "nativepointer";
|
|
} else if (arg->type()->isIntegerEnum() || arg->type()->isIntegerFlags()) {
|
|
returned += "int";
|
|
} else {
|
|
returned += arg->type()->name().replace("[]", "_3").replace(".", "_");
|
|
}
|
|
}
|
|
return returned;
|
|
}
|
|
|
|
bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const
|
|
{
|
|
uint result = compareTo(&other);
|
|
return result & NameLessThan;
|
|
}
|
|
|
|
|
|
/*!
|
|
Returns a mask of CompareResult describing how this function is
|
|
compares to another function
|
|
*/
|
|
uint AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const
|
|
{
|
|
uint result = 0;
|
|
|
|
// Enclosing class...
|
|
if (ownerClass() == other->ownerClass()) {
|
|
result |= EqualImplementor;
|
|
}
|
|
|
|
// Attributes
|
|
if (attributes() == other->attributes()) {
|
|
result |= EqualAttributes;
|
|
}
|
|
|
|
// Compare types
|
|
AbstractMetaType *t = type();
|
|
AbstractMetaType *ot = other->type();
|
|
if ((!t && !ot) || ((t && ot && t->name() == ot->name()))) {
|
|
result |= EqualReturnType;
|
|
}
|
|
|
|
// Compare names
|
|
int cmp = originalName().compare(other->originalName());
|
|
|
|
if (cmp < 0) {
|
|
result |= NameLessThan;
|
|
} else if (cmp == 0) {
|
|
result |= EqualName;
|
|
}
|
|
|
|
// compare name after modification...
|
|
cmp = modifiedName().compare(other->modifiedName());
|
|
if (cmp == 0)
|
|
result |= EqualModifiedName;
|
|
|
|
// Compare arguments...
|
|
AbstractMetaArgumentList min_arguments;
|
|
AbstractMetaArgumentList max_arguments;
|
|
if (arguments().size() < other->arguments().size()) {
|
|
min_arguments = arguments();
|
|
max_arguments = other->arguments();
|
|
} else {
|
|
min_arguments = other->arguments();
|
|
max_arguments = arguments();
|
|
}
|
|
|
|
int min_count = min_arguments.size();
|
|
int max_count = max_arguments.size();
|
|
bool same = true;
|
|
for (int i=0; i<max_count; ++i) {
|
|
if (i < min_count) {
|
|
const AbstractMetaArgument *min_arg = min_arguments.at(i);
|
|
const AbstractMetaArgument *max_arg = max_arguments.at(i);
|
|
if (min_arg->type()->name() != max_arg->type()->name()
|
|
&& (min_arg->defaultValueExpression().isEmpty() || max_arg->defaultValueExpression().isEmpty())) {
|
|
same = false;
|
|
break;
|
|
}
|
|
} else {
|
|
if (max_arguments.at(i)->defaultValueExpression().isEmpty()) {
|
|
same = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (same)
|
|
result |= min_count == max_count ? EqualArguments : EqualDefaultValueOverload;
|
|
|
|
return result;
|
|
}
|
|
|
|
AbstractMetaFunction *AbstractMetaFunction::copy() const
|
|
{
|
|
AbstractMetaFunction *cpy = new AbstractMetaFunction;
|
|
cpy->setName(name());
|
|
cpy->setOriginalName(originalName());
|
|
cpy->setOwnerClass(ownerClass());
|
|
cpy->setImplementingClass(implementingClass());
|
|
cpy->setInterfaceClass(interfaceClass());
|
|
cpy->setFunctionType(functionType());
|
|
cpy->setAttributes(attributes());
|
|
cpy->setDeclaringClass(declaringClass());
|
|
if (type())
|
|
cpy->setType(type()->copy());
|
|
cpy->setConstant(isConstant());
|
|
cpy->setOriginalAttributes(originalAttributes());
|
|
|
|
foreach (AbstractMetaArgument *arg, arguments())
|
|
cpy->addArgument(arg->copy());
|
|
|
|
Q_ASSERT((!type() && !cpy->type())
|
|
|| (type()->instantiations() == cpy->type()->instantiations()));
|
|
|
|
return cpy;
|
|
}
|
|
|
|
QStringList AbstractMetaFunction::introspectionCompatibleSignatures(const QStringList &resolvedArguments) const
|
|
{
|
|
AbstractMetaArgumentList arguments = this->arguments();
|
|
if (arguments.size() == resolvedArguments.size()) {
|
|
return (QStringList() << QMetaObject::normalizedSignature((name() + "(" + resolvedArguments.join(",") + ")").toUtf8().constData()));
|
|
} else {
|
|
QStringList returned;
|
|
|
|
AbstractMetaArgument *argument = arguments.at(resolvedArguments.size());
|
|
QStringList minimalTypeSignature = argument->type()->minimalSignature().split("::");
|
|
for (int i=0; i<minimalTypeSignature.size(); ++i) {
|
|
returned += introspectionCompatibleSignatures(QStringList(resolvedArguments)
|
|
<< QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join("::"));
|
|
}
|
|
|
|
return returned;
|
|
}
|
|
}
|
|
|
|
QString AbstractMetaFunction::signature() const
|
|
{
|
|
QString s(m_original_name);
|
|
|
|
s += "(";
|
|
|
|
for (int i=0; i<m_arguments.count(); ++i) {
|
|
if (i > 0)
|
|
s += ", ";
|
|
AbstractMetaArgument *a = m_arguments.at(i);
|
|
s += a->type()->cppSignature();
|
|
|
|
// We need to have the argument names in the qdoc files
|
|
s += " ";
|
|
s += a->argumentName();
|
|
}
|
|
s += ")";
|
|
|
|
if (isConstant())
|
|
s += " const";
|
|
|
|
return s;
|
|
}
|
|
|
|
int AbstractMetaFunction::actualMinimumArgumentCount() const
|
|
{
|
|
AbstractMetaArgumentList arguments = this->arguments();
|
|
|
|
int count = 0;
|
|
for (int i=0; i<arguments.size(); ++i && ++count) {
|
|
if (argumentRemoved(i + 1)) --count;
|
|
else if (!arguments.at(i)->defaultValueExpression().isEmpty()) break;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
// Returns reference counts for argument at idx, or all arguments if idx == -2
|
|
QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const
|
|
{
|
|
QList<ReferenceCount> returned;
|
|
|
|
FunctionModificationList mods = this->modifications(cls);
|
|
foreach (FunctionModification mod, mods) {
|
|
QList<ArgumentModification> argument_mods = mod.argument_mods;
|
|
foreach (ArgumentModification argument_mod, argument_mods) {
|
|
if (argument_mod.index != idx && idx != -2)
|
|
continue;
|
|
returned += argument_mod.referenceCounts;
|
|
}
|
|
}
|
|
|
|
return returned;
|
|
}
|
|
|
|
QString AbstractMetaFunction::replacedDefaultExpression(const AbstractMetaClass *cls, int key) const
|
|
{
|
|
FunctionModificationList modifications = this->modifications(cls);
|
|
foreach (FunctionModification modification, modifications) {
|
|
QList<ArgumentModification> argument_modifications = modification.argument_mods;
|
|
foreach (ArgumentModification argument_modification, argument_modifications) {
|
|
if (argument_modification.index == key
|
|
&& !argument_modification.replaced_default_expression.isEmpty()) {
|
|
return argument_modification.replaced_default_expression;
|
|
}
|
|
}
|
|
}
|
|
|
|
return QString();
|
|
}
|
|
|
|
bool AbstractMetaFunction::removedDefaultExpression(const AbstractMetaClass *cls, int key) const
|
|
{
|
|
FunctionModificationList modifications = this->modifications(cls);
|
|
foreach (FunctionModification modification, modifications) {
|
|
QList<ArgumentModification> argument_modifications = modification.argument_mods;
|
|
foreach (ArgumentModification argument_modification, argument_modifications) {
|
|
if (argument_modification.index == key
|
|
&& argument_modification.removed_default_expression) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool AbstractMetaFunction::resetObjectAfterUse(int argument_idx) const
|
|
{
|
|
const AbstractMetaClass *cls = declaringClass();
|
|
FunctionModificationList modifications = this->modifications(cls);
|
|
foreach (FunctionModification modification, modifications) {
|
|
QList<ArgumentModification> argumentModifications = modification.argument_mods;
|
|
foreach (ArgumentModification argumentModification, argumentModifications) {
|
|
if (argumentModification.index == argument_idx && argumentModification.reset_after_use)
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
QString AbstractMetaFunction::nullPointerDefaultValue(const AbstractMetaClass *mainClass, int argument_idx) const
|
|
{
|
|
Q_ASSERT(nullPointersDisabled(mainClass, argument_idx));
|
|
|
|
const AbstractMetaClass *cls = mainClass;
|
|
if (cls == 0)
|
|
cls = implementingClass();
|
|
|
|
do {
|
|
FunctionModificationList modifications = this->modifications(cls);
|
|
foreach (FunctionModification modification, modifications) {
|
|
QList<ArgumentModification> argument_modifications = modification.argument_mods;
|
|
foreach (ArgumentModification argument_modification, argument_modifications) {
|
|
if (argument_modification.index == argument_idx
|
|
&& argument_modification.no_null_pointers) {
|
|
return argument_modification.null_pointer_default_value;
|
|
}
|
|
}
|
|
}
|
|
|
|
cls = cls->baseClass();
|
|
} while (cls != 0 && mainClass == 0); // Once when mainClass != 0, or once for all base classes of implementing class
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
bool AbstractMetaFunction::nullPointersDisabled(const AbstractMetaClass *mainClass, int argument_idx) const
|
|
{
|
|
const AbstractMetaClass *cls = mainClass;
|
|
if (cls == 0)
|
|
cls = implementingClass();
|
|
|
|
do {
|
|
FunctionModificationList modifications = this->modifications(cls);
|
|
foreach (FunctionModification modification, modifications) {
|
|
QList<ArgumentModification> argument_modifications = modification.argument_mods;
|
|
foreach (ArgumentModification argument_modification, argument_modifications) {
|
|
if (argument_modification.index == argument_idx
|
|
&& argument_modification.no_null_pointers) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
cls = cls->baseClass();
|
|
} while (cls != 0 && mainClass == 0); // Once when mainClass != 0, or once for all base classes of implementing class
|
|
|
|
return false;
|
|
}
|
|
|
|
QString AbstractMetaFunction::conversionRule(TypeSystem::Language language, int key) const
|
|
{
|
|
FunctionModificationList modifications = this->modifications(declaringClass());
|
|
foreach (FunctionModification modification, modifications) {
|
|
QList<ArgumentModification> argument_modifications = modification.argument_mods;
|
|
foreach (ArgumentModification argument_modification, argument_modifications) {
|
|
if (argument_modification.index != key)
|
|
continue;
|
|
|
|
foreach (CodeSnip snip, argument_modification.conversion_rules) {
|
|
if (snip.language == language && !snip.code().isEmpty())
|
|
return snip.code();
|
|
}
|
|
}
|
|
}
|
|
|
|
return QString();
|
|
}
|
|
|
|
QString AbstractMetaFunction::argumentReplaced(int key) const
|
|
{
|
|
FunctionModificationList modifications = this->modifications(declaringClass());
|
|
foreach (FunctionModification modification, modifications) {
|
|
QList<ArgumentModification> argument_modifications = modification.argument_mods;
|
|
foreach (ArgumentModification argument_modification, argument_modifications) {
|
|
if (argument_modification.index == key && !argument_modification.replace_value.isEmpty()) {
|
|
return argument_modification.replace_value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
bool AbstractMetaFunction::argumentRemoved(int key) const
|
|
{
|
|
FunctionModificationList modifications = this->modifications(declaringClass());
|
|
foreach (FunctionModification modification, modifications) {
|
|
QList<ArgumentModification> argument_modifications = modification.argument_mods;
|
|
foreach (ArgumentModification argument_modification, argument_modifications) {
|
|
if (argument_modification.index == key) {
|
|
if (argument_modification.removed) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool AbstractMetaFunction::isVirtualSlot() const
|
|
{
|
|
FunctionModificationList modifications = this->modifications(declaringClass());
|
|
foreach (FunctionModification modification, modifications) {
|
|
if (modification.isVirtualSlot())
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool AbstractMetaFunction::disabledGarbageCollection(const AbstractMetaClass *cls, int key) const
|
|
{
|
|
FunctionModificationList modifications = this->modifications(cls);
|
|
foreach (FunctionModification modification, modifications) {
|
|
QList<ArgumentModification> argument_modifications = modification.argument_mods;
|
|
foreach (ArgumentModification argument_modification, argument_modifications) {
|
|
if (argument_modification.index != key)
|
|
continue;
|
|
|
|
foreach (TypeSystem::Ownership ownership, argument_modification.ownerships.values()) {
|
|
if (ownership == TypeSystem::CppOwnership)
|
|
return true;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool AbstractMetaFunction::isDeprecated() const
|
|
{
|
|
FunctionModificationList modifications = this->modifications(declaringClass());
|
|
foreach (FunctionModification modification, modifications) {
|
|
if (modification.isDeprecated())
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const
|
|
{
|
|
FunctionModificationList modifications = this->modifications(cls);
|
|
foreach (FunctionModification modification, modifications) {
|
|
QList<ArgumentModification> argument_modifications = modification.argument_mods;
|
|
foreach (ArgumentModification argument_modification, argument_modifications) {
|
|
if (argument_modification.index == key)
|
|
return argument_modification.ownerships.value(language, TypeSystem::InvalidOwnership);
|
|
}
|
|
}
|
|
|
|
return TypeSystem::InvalidOwnership;
|
|
}
|
|
|
|
bool AbstractMetaFunction::isRemovedFromAllLanguages(const AbstractMetaClass *cls) const
|
|
{
|
|
return isRemovedFrom(cls, TypeSystem::All);
|
|
}
|
|
|
|
bool AbstractMetaFunction::isRemovedFrom(const AbstractMetaClass *cls, TypeSystem::Language language) const
|
|
{
|
|
FunctionModificationList modifications = this->modifications(cls);
|
|
foreach (FunctionModification modification, modifications) {
|
|
if ((modification.removal & language) == language)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QString AbstractMetaFunction::typeReplaced(int key) const
|
|
{
|
|
FunctionModificationList modifications = this->modifications(declaringClass());
|
|
foreach (FunctionModification modification, modifications) {
|
|
QList<ArgumentModification> argument_modifications = modification.argument_mods;
|
|
foreach (ArgumentModification argument_modification, argument_modifications) {
|
|
if (argument_modification.index == key
|
|
&& !argument_modification.modified_type.isEmpty()) {
|
|
return argument_modification.modified_type;
|
|
}
|
|
}
|
|
}
|
|
|
|
return QString();
|
|
}
|
|
|
|
QString AbstractMetaFunction::minimalSignature() const
|
|
{
|
|
if (!m_cached_minimal_signature.isEmpty())
|
|
return m_cached_minimal_signature;
|
|
|
|
QString minimalSignature = originalName() + "(";
|
|
AbstractMetaArgumentList arguments = this->arguments();
|
|
|
|
for (int i=0; i<arguments.count(); ++i) {
|
|
AbstractMetaType *t = arguments.at(i)->type();
|
|
|
|
if (i > 0)
|
|
minimalSignature += ",";
|
|
|
|
minimalSignature += t->minimalSignature();
|
|
}
|
|
minimalSignature += ")";
|
|
if (isConstant())
|
|
minimalSignature += "const";
|
|
|
|
minimalSignature = QMetaObject::normalizedSignature(minimalSignature.toLocal8Bit().constData());
|
|
m_cached_minimal_signature = minimalSignature;
|
|
|
|
return minimalSignature;
|
|
}
|
|
|
|
FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass *implementor) const
|
|
{
|
|
Q_ASSERT(implementor);
|
|
return implementor->typeEntry()->functionModifications(minimalSignature());
|
|
}
|
|
|
|
bool AbstractMetaFunction::hasModifications(const AbstractMetaClass *implementor) const
|
|
{
|
|
FunctionModificationList mods = modifications(implementor);
|
|
return mods.count() > 0;
|
|
}
|
|
|
|
QString AbstractMetaFunction::modifiedName() const
|
|
{
|
|
if (m_cached_modified_name.isEmpty()) {
|
|
FunctionModificationList mods = modifications(implementingClass());
|
|
foreach (FunctionModification mod, mods) {
|
|
if (mod.isRenameModifier()) {
|
|
m_cached_modified_name = mod.renamedToName;
|
|
break;
|
|
}
|
|
}
|
|
if (m_cached_modified_name.isEmpty())
|
|
m_cached_modified_name = name();
|
|
}
|
|
return m_cached_modified_name;
|
|
}
|
|
|
|
QString AbstractMetaFunction::targetLangSignature(bool minimal) const
|
|
{
|
|
QString s;
|
|
|
|
// Attributes...
|
|
if (!minimal) {
|
|
#if 0 // jambi
|
|
if (isPublic()) s += "public ";
|
|
else if (isProtected()) s += "protected ";
|
|
else if (isPrivate()) s += "private ";
|
|
|
|
// if (isNative()) s += "native ";
|
|
// else
|
|
if (isFinalInTargetLang()) s += "final ";
|
|
else if (isAbstract()) s += "abstract ";
|
|
|
|
if (isStatic()) s += "static ";
|
|
#endif
|
|
// Return type
|
|
if (type())
|
|
s += type()->name() + " ";
|
|
else
|
|
s += "void ";
|
|
}
|
|
|
|
s += modifiedName();
|
|
s += "(";
|
|
|
|
int j = 0;
|
|
for (int i=0; i<m_arguments.size(); ++i) {
|
|
if (argumentRemoved(i+1))
|
|
continue;
|
|
if (j != 0) {
|
|
s += ",";
|
|
if (!minimal)
|
|
s += QLatin1Char(' ');
|
|
}
|
|
s += m_arguments.at(i)->type()->name();
|
|
|
|
if (!minimal) {
|
|
s += " ";
|
|
s += m_arguments.at(i)->argumentName();
|
|
}
|
|
++j;
|
|
}
|
|
|
|
s += ")";
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b)
|
|
{
|
|
return a->signature() < b->signature();
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* AbstractMetaClass
|
|
*/
|
|
AbstractMetaClass::~AbstractMetaClass()
|
|
{
|
|
qDeleteAll(m_functions);
|
|
qDeleteAll(m_fields);
|
|
}
|
|
|
|
/*AbstractMetaClass *AbstractMetaClass::copy() const
|
|
{
|
|
AbstractMetaClass *cls = new AbstractMetaClass;
|
|
cls->setAttributes(attributes());
|
|
cls->setBaseClass(baseClass());
|
|
cls->setTypeEntry(typeEntry());
|
|
foreach (AbstractMetaFunction *function, functions()) {
|
|
AbstractMetaFunction *copy = function->copy();
|
|
function->setImplementingClass(cls);
|
|
cls->addFunction(copy);
|
|
}
|
|
cls->setEnums(enums());
|
|
foreach (const AbstractMetaField *field, fields()) {
|
|
AbstractMetaField *copy = field->copy();
|
|
copy->setEnclosingClass(cls);
|
|
cls->addField(copy);
|
|
}
|
|
cls->setInterfaces(interfaces());
|
|
|
|
return cls;
|
|
}*/
|
|
|
|
/*******************************************************************************
|
|
* Returns true if this class is a subclass of the given class
|
|
*/
|
|
bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const
|
|
{
|
|
Q_ASSERT(cls != 0);
|
|
|
|
const AbstractMetaClass *clazz = this;
|
|
while (clazz != 0) {
|
|
if (clazz == cls)
|
|
return true;
|
|
|
|
clazz = clazz->baseClass();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Constructs an interface based on the functions and enums in this
|
|
* class and returns it...
|
|
*/
|
|
AbstractMetaClass *AbstractMetaClass::extractInterface()
|
|
{
|
|
Q_ASSERT(typeEntry()->designatedInterface());
|
|
|
|
if (m_extracted_interface == 0) {
|
|
AbstractMetaClass *iface = new AbstractMetaClass;
|
|
iface->setAttributes(attributes());
|
|
iface->setBaseClass(0);
|
|
iface->setPrimaryInterfaceImplementor(this);
|
|
|
|
iface->setTypeEntry(typeEntry()->designatedInterface());
|
|
|
|
foreach (AbstractMetaFunction *function, functions()) {
|
|
if (!function->isConstructor())
|
|
iface->addFunction(function->copy());
|
|
}
|
|
|
|
// iface->setEnums(enums());
|
|
// setEnums(AbstractMetaEnumList());
|
|
|
|
foreach (const AbstractMetaField *field, fields()) {
|
|
if (field->isPublic()) {
|
|
AbstractMetaField *new_field = field->copy();
|
|
new_field->setEnclosingClass(iface);
|
|
iface->addField(new_field);
|
|
}
|
|
}
|
|
|
|
m_extracted_interface = iface;
|
|
addInterface(iface);
|
|
}
|
|
|
|
return m_extracted_interface;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Returns a list of all the functions with a given name
|
|
*/
|
|
AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const
|
|
{
|
|
AbstractMetaFunctionList returned;
|
|
AbstractMetaFunctionList functions = this->functions();
|
|
foreach (AbstractMetaFunction *function, functions) {
|
|
if (function->name() == name)
|
|
returned.append(function);
|
|
}
|
|
|
|
return returned;
|
|
}
|
|
|
|
bool AbstractMetaClass::hasDefaultIsNull() const
|
|
{
|
|
foreach(const AbstractMetaFunction* fun, queryFunctionsByName("isNull")) {
|
|
if (fun->actualMinimumArgumentCount()==0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Returns all reference count modifications for any function in the class
|
|
*/
|
|
QList<ReferenceCount> AbstractMetaClass::referenceCounts() const
|
|
{
|
|
QList<ReferenceCount> returned;
|
|
|
|
AbstractMetaFunctionList functions = this->functions();
|
|
foreach (AbstractMetaFunction *function, functions) {
|
|
returned += function->referenceCounts(this);
|
|
}
|
|
|
|
return returned;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Returns a list of all the functions retrieved during parsing which should
|
|
* be added to the Java API.
|
|
*/
|
|
AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const
|
|
{
|
|
int default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang;
|
|
|
|
// Interfaces don't implement functions
|
|
default_flags |= isInterface() ? 0 : ClassImplements;
|
|
|
|
// Only public functions in final classes
|
|
// default_flags |= isFinal() ? WasPublic : 0;
|
|
int public_flags = isFinal() ? WasPublic : 0;
|
|
|
|
// Constructors
|
|
AbstractMetaFunctionList returned = queryFunctions(Constructors | default_flags | public_flags);
|
|
|
|
// Final functions
|
|
returned += queryFunctions(FinalInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags);
|
|
|
|
// Virtual functions
|
|
returned += queryFunctions(VirtualInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags);
|
|
|
|
// Static functions
|
|
returned += queryFunctions(StaticFunctions | default_flags | public_flags);
|
|
|
|
// Empty, private functions, since they aren't caught by the other ones
|
|
returned += queryFunctions(Empty | Invisible);
|
|
|
|
return returned;
|
|
}
|
|
|
|
AbstractMetaFunctionList AbstractMetaClass::virtualFunctions() const
|
|
{
|
|
AbstractMetaFunctionList list = functionsInShellClass();
|
|
|
|
AbstractMetaFunctionList returned;
|
|
foreach (AbstractMetaFunction *f, list) {
|
|
if (!f->isFinalInCpp() || f->isVirtualSlot())
|
|
returned += f;
|
|
}
|
|
|
|
return returned;
|
|
}
|
|
|
|
AbstractMetaFunctionList AbstractMetaClass::nonVirtualShellFunctions() const
|
|
{
|
|
AbstractMetaFunctionList list = functionsInShellClass();
|
|
AbstractMetaFunctionList returned;
|
|
foreach (AbstractMetaFunction *f, list) {
|
|
if (f->isFinalInCpp() && !f->isVirtualSlot())
|
|
returned += f;
|
|
}
|
|
|
|
return returned;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Returns a list of all functions that should be declared and implemented in
|
|
* the shell class which is generated as a wrapper on top of the actual C++ class
|
|
*/
|
|
AbstractMetaFunctionList AbstractMetaClass::functionsInShellClass() const
|
|
{
|
|
// Only functions and only protected and public functions
|
|
int default_flags = NormalFunctions | Visible | WasVisible | NotRemovedFromShell;
|
|
|
|
// All virtual functions
|
|
AbstractMetaFunctionList returned = queryFunctions(VirtualFunctions | default_flags);
|
|
|
|
// All functions explicitly set to be implemented by the shell class
|
|
// (mainly superclass functions that are hidden by other declarations)
|
|
returned += queryFunctions(ForcedShellFunctions | default_flags);
|
|
|
|
// All functions explicitly set to be virtual slots
|
|
returned += queryFunctions(VirtualSlots | default_flags);
|
|
|
|
return returned;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Returns a list of all functions that require a public override function to
|
|
* be generated in the shell class. This includes all functions that were originally
|
|
* protected in the superclass.
|
|
*/
|
|
AbstractMetaFunctionList AbstractMetaClass::publicOverrideFunctions() const
|
|
{
|
|
return queryFunctions(NormalFunctions | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang)
|
|
+ queryFunctions(Signals | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang);
|
|
}
|
|
|
|
AbstractMetaFunctionList AbstractMetaClass::virtualOverrideFunctions() const
|
|
{
|
|
return queryFunctions(NormalFunctions | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell) +
|
|
queryFunctions(Signals | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell);
|
|
}
|
|
|
|
void AbstractMetaClass::sortFunctions()
|
|
{
|
|
qSort(m_functions.begin(), m_functions.end(), function_sorter);
|
|
}
|
|
|
|
void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions)
|
|
{
|
|
m_functions = functions;
|
|
|
|
// Functions must be sorted by name before next loop
|
|
sortFunctions();
|
|
|
|
QString currentName;
|
|
bool hasVirtuals = false;
|
|
AbstractMetaFunctionList final_functions;
|
|
foreach (AbstractMetaFunction *f, m_functions) {
|
|
f->setOwnerClass(this);
|
|
|
|
m_has_virtual_slots |= f->isVirtualSlot();
|
|
m_has_virtuals |= !f->isFinal() || f->isVirtualSlot();
|
|
m_has_nonpublic |= !f->isPublic();
|
|
|
|
// If we have non-virtual overloads of a virtual function, we have to implement
|
|
// all the overloads in the shell class to override the hiding rule
|
|
if (currentName == f->name()) {
|
|
hasVirtuals = hasVirtuals || !f->isFinal();
|
|
if (f->isFinal())
|
|
final_functions += f;
|
|
} else {
|
|
if (hasVirtuals && final_functions.size() > 0) {
|
|
foreach (AbstractMetaFunction *final_function, final_functions) {
|
|
*final_function += AbstractMetaAttributes::ForceShellImplementation;
|
|
|
|
QString warn = QString("hiding of function '%1' in class '%2'")
|
|
.arg(final_function->name()).arg(name());
|
|
ReportHandler::warning(warn);
|
|
}
|
|
}
|
|
|
|
hasVirtuals = !f->isFinal();
|
|
final_functions.clear();
|
|
if (f->isFinal())
|
|
final_functions += f;
|
|
currentName = f->name();
|
|
}
|
|
}
|
|
|
|
#ifndef QT_NO_DEBUG
|
|
bool duplicate_function = false;
|
|
for (int j=0; j<m_functions.size(); ++j) {
|
|
FunctionModificationList mods = m_functions.at(j)->modifications(m_functions.at(j)->implementingClass());
|
|
|
|
bool removed = false;
|
|
foreach (const FunctionModification &mod, mods) {
|
|
if (mod.isRemoveModifier()) {
|
|
removed = true;
|
|
break ;
|
|
}
|
|
}
|
|
if (removed)
|
|
continue ;
|
|
|
|
for (int i=0; i<m_functions.size() - 1; ++i) {
|
|
if (j == i)
|
|
continue;
|
|
|
|
mods = m_functions.at(i)->modifications(m_functions.at(i)->implementingClass());
|
|
bool removed = false;
|
|
foreach (const FunctionModification &mod, mods) {
|
|
if (mod.isRemoveModifier()) {
|
|
removed = true;
|
|
break ;
|
|
}
|
|
}
|
|
if (removed)
|
|
continue ;
|
|
|
|
uint cmp = m_functions.at(i)->compareTo(m_functions.at(j));
|
|
if ((cmp & AbstractMetaFunction::EqualName) && (cmp & AbstractMetaFunction::EqualArguments)) {
|
|
printf("%s.%s mostly equal to %s.%s\n",
|
|
qPrintable(m_functions.at(i)->implementingClass()->typeEntry()->qualifiedCppName()),
|
|
qPrintable(m_functions.at(i)->signature()),
|
|
qPrintable(m_functions.at(j)->implementingClass()->typeEntry()->qualifiedCppName()),
|
|
qPrintable(m_functions.at(j)->signature()));
|
|
duplicate_function = true;
|
|
}
|
|
}
|
|
}
|
|
//Q_ASSERT(!duplicate_function);
|
|
#endif
|
|
}
|
|
|
|
bool AbstractMetaClass::hasFieldAccessors() const
|
|
{
|
|
foreach (const AbstractMetaField *field, fields()) {
|
|
if (field->getter() || field->setter())
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool AbstractMetaClass::hasDefaultToStringFunction() const
|
|
{
|
|
foreach (AbstractMetaFunction *f, queryFunctionsByName("toString")) {
|
|
if (f->actualMinimumArgumentCount() == 0) {
|
|
return true;
|
|
}
|
|
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void AbstractMetaClass::addFunction(AbstractMetaFunction *function)
|
|
{
|
|
function->setOwnerClass(this);
|
|
|
|
if (!function->isDestructor()) {
|
|
m_functions << function;
|
|
qSort(m_functions.begin(), m_functions.end(), function_sorter);
|
|
}
|
|
|
|
|
|
m_has_virtual_slots |= function->isVirtualSlot();
|
|
m_has_virtuals |= !function->isFinal() || function->isVirtualSlot();
|
|
m_has_nonpublic |= !function->isPublic();
|
|
}
|
|
|
|
bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const
|
|
{
|
|
if (!other->isSignal())
|
|
return false;
|
|
|
|
foreach (const AbstractMetaFunction *f, functions()) {
|
|
if (f->isSignal() && f->compareTo(other) & AbstractMetaFunction::EqualName)
|
|
return other->modifiedName() == f->modifiedName();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
QString AbstractMetaClass::name() const
|
|
{
|
|
return QString(m_type_entry->targetLangName()).replace("::", "_");
|
|
}
|
|
|
|
bool AbstractMetaClass::hasFunction(const QString &str) const
|
|
{
|
|
foreach (const AbstractMetaFunction *f, functions())
|
|
if (f->name() == str)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/* Returns true if this class has one or more functions that are
|
|
protected. If a class has protected members we need to generate a
|
|
shell class with public accessors to the protected functions, so
|
|
they can be called from the native functions.
|
|
*/
|
|
bool AbstractMetaClass::hasProtectedFunctions() const {
|
|
foreach (AbstractMetaFunction *func, m_functions) {
|
|
if (func->isProtected())
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool AbstractMetaClass::generateShellClass() const
|
|
{
|
|
return m_force_shell_class ||
|
|
(!isFinal()
|
|
&& (hasVirtualFunctions()
|
|
|| hasProtectedFunctions()
|
|
|| hasFieldAccessors()));
|
|
}
|
|
|
|
QPropertySpec *AbstractMetaClass::propertySpecForRead(const QString &name) const
|
|
{
|
|
for (int i=0; i<m_property_specs.size(); ++i)
|
|
if (name == m_property_specs.at(i)->read())
|
|
return m_property_specs.at(i);
|
|
return 0;
|
|
}
|
|
|
|
QPropertySpec *AbstractMetaClass::propertySpecForWrite(const QString &name) const
|
|
{
|
|
for (int i=0; i<m_property_specs.size(); ++i)
|
|
if (name == m_property_specs.at(i)->write())
|
|
return m_property_specs.at(i);
|
|
return 0;
|
|
}
|
|
|
|
QPropertySpec *AbstractMetaClass::propertySpecForReset(const QString &name) const
|
|
{
|
|
for (int i=0; i<m_property_specs.size(); ++i) {
|
|
if (name == m_property_specs.at(i)->reset())
|
|
return m_property_specs.at(i);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func)
|
|
{
|
|
foreach (const AbstractMetaFunction *f, l) {
|
|
if ((f->compareTo(func) & AbstractMetaFunction::PrettySimilar) == AbstractMetaFunction::PrettySimilar)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
AbstractMetaField::AbstractMetaField() : m_getter(0), m_setter(0), m_class(0)
|
|
{
|
|
}
|
|
|
|
AbstractMetaField::~AbstractMetaField()
|
|
{
|
|
delete m_setter;
|
|
delete m_getter;
|
|
}
|
|
ushort painters; // refcount
|
|
AbstractMetaField *AbstractMetaField::copy() const
|
|
{
|
|
AbstractMetaField *returned = new AbstractMetaField;
|
|
returned->setEnclosingClass(0);
|
|
returned->setAttributes(attributes());
|
|
returned->setName(name());
|
|
returned->setType(type()->copy());
|
|
returned->setOriginalAttributes(originalAttributes());
|
|
|
|
return returned;
|
|
}
|
|
|
|
static QString upCaseFirst(const QString &str) {
|
|
Q_ASSERT(!str.isEmpty());
|
|
QString s = str;
|
|
s[0] = s.at(0).toUpper();
|
|
return s;
|
|
}
|
|
|
|
static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QString &name, uint type) {
|
|
AbstractMetaFunction *f = new AbstractMetaFunction;
|
|
|
|
|
|
|
|
f->setName(name);
|
|
f->setOriginalName(name);
|
|
f->setOwnerClass(g->enclosingClass());
|
|
f->setImplementingClass(g->enclosingClass());
|
|
f->setDeclaringClass(g->enclosingClass());
|
|
|
|
uint attr = AbstractMetaAttributes::Native
|
|
| AbstractMetaAttributes::Final
|
|
| type;
|
|
if (g->isStatic())
|
|
attr |= AbstractMetaAttributes::Static;
|
|
if (g->isPublic())
|
|
attr |= AbstractMetaAttributes::Public;
|
|
else if (g->isProtected())
|
|
attr |= AbstractMetaAttributes::Protected;
|
|
else
|
|
attr |= AbstractMetaAttributes::Private;
|
|
f->setAttributes(attr);
|
|
f->setOriginalAttributes(attr);
|
|
|
|
FieldModificationList mods = g->modifications();
|
|
foreach (FieldModification mod, mods) {
|
|
if (mod.isRenameModifier())
|
|
f->setName(mod.renamedTo());
|
|
if (mod.isAccessModifier()) {
|
|
if (mod.isPrivate())
|
|
f->setVisibility(AbstractMetaAttributes::Private);
|
|
else if (mod.isProtected())
|
|
f->setVisibility(AbstractMetaAttributes::Protected);
|
|
else if (mod.isPublic())
|
|
f->setVisibility(AbstractMetaAttributes::Public);
|
|
else if (mod.isFriendly())
|
|
f->setVisibility(AbstractMetaAttributes::Friendly);
|
|
}
|
|
|
|
}
|
|
return f;
|
|
}
|
|
|
|
FieldModificationList AbstractMetaField::modifications() const
|
|
{
|
|
FieldModificationList mods = enclosingClass()->typeEntry()->fieldModifications();
|
|
FieldModificationList returned;
|
|
|
|
foreach (FieldModification mod, mods) {
|
|
if (mod.name == name())
|
|
returned += mod;
|
|
}
|
|
|
|
return returned;
|
|
}
|
|
|
|
const AbstractMetaFunction *AbstractMetaField::setter() const
|
|
{
|
|
if (m_setter == 0) {
|
|
m_setter = createXetter(this,
|
|
name(),
|
|
AbstractMetaAttributes::SetterFunction);
|
|
AbstractMetaArgumentList arguments;
|
|
AbstractMetaArgument *argument = new AbstractMetaArgument;
|
|
argument->setType(type()->copy());
|
|
argument->setName(name());
|
|
arguments.append(argument);
|
|
m_setter->setArguments(arguments);
|
|
}
|
|
return m_setter;
|
|
}
|
|
|
|
const AbstractMetaFunction *AbstractMetaField::getter() const
|
|
{
|
|
if (m_getter == 0) {
|
|
m_getter = createXetter(this,
|
|
name(),
|
|
AbstractMetaAttributes::GetterFunction);
|
|
m_getter->setType(type());
|
|
}
|
|
|
|
return m_getter;
|
|
}
|
|
|
|
|
|
bool AbstractMetaClass::hasConstructors() const
|
|
{
|
|
return queryFunctions(Constructors).size() != 0;
|
|
}
|
|
|
|
void AbstractMetaClass::addDefaultConstructor()
|
|
{
|
|
AbstractMetaFunction *f = new AbstractMetaFunction;
|
|
f->setName(name());
|
|
f->setOwnerClass(this);
|
|
f->setFunctionType(AbstractMetaFunction::ConstructorFunction);
|
|
f->setArguments(AbstractMetaArgumentList());
|
|
f->setDeclaringClass(this);
|
|
|
|
uint attr = AbstractMetaAttributes::Native;
|
|
attr |= AbstractMetaAttributes::Public;
|
|
f->setAttributes(attr);
|
|
f->setImplementingClass(this);
|
|
f->setOriginalAttributes(f->attributes());
|
|
|
|
addFunction(f);
|
|
}
|
|
|
|
bool AbstractMetaClass::hasFunction(const AbstractMetaFunction *f) const
|
|
{
|
|
return functions_contains(m_functions, f);
|
|
}
|
|
|
|
/* Goes through the list of functions and returns a list of all
|
|
functions matching all of the criteria in \a query.
|
|
*/
|
|
|
|
AbstractMetaFunctionList AbstractMetaClass::queryFunctions(uint query) const
|
|
{
|
|
AbstractMetaFunctionList functions;
|
|
|
|
foreach (AbstractMetaFunction *f, m_functions) {
|
|
|
|
if ((query & VirtualSlots) && !f->isVirtualSlot())
|
|
continue;
|
|
|
|
if ((query & NotRemovedFromTargetLang) && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode)) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & NotRemovedFromTargetLang) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode)) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & NotRemovedFromShell) && f->isRemovedFrom(f->implementingClass(), TypeSystem::ShellCode)) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & NotRemovedFromShell) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::ShellCode)) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & Visible) && f->isPrivate()) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & VirtualInTargetLangFunctions) && f->isFinalInTargetLang()) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & Invisible) && !f->isPrivate()) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & Empty) && !f->isEmptyFunction()) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & WasPublic) && !f->wasPublic()) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & WasVisible) && f->wasPrivate()) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & WasProtected) && !f->wasProtected()) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & ClassImplements) && f->ownerClass() != f->implementingClass()) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & Inconsistent) && (f->isFinalInTargetLang() || !f->isFinalInCpp() || f->isStatic())) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang()) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & FinalInCppFunctions) && !f->isFinalInCpp()) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & VirtualInCppFunctions) && f->isFinalInCpp()) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & Signals) && (!f->isSignal())) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & ForcedShellFunctions)
|
|
&& (!f->isForcedShellImplementation()
|
|
|| !f->isFinal())) {
|
|
continue;
|
|
}
|
|
|
|
if (((query & Constructors) && (!f->isConstructor()
|
|
|| f->ownerClass() != f->implementingClass()))
|
|
|| (f->isConstructor() && (query & Constructors) == 0)) {
|
|
continue;
|
|
}
|
|
|
|
// Destructors are never included in the functions of a class currently
|
|
/*
|
|
if ((query & Destructors) && (!f->isDestructor()
|
|
|| f->ownerClass() != f->implementingClass())
|
|
|| f->isDestructor() && (query & Destructors) == 0) {
|
|
continue;
|
|
}*/
|
|
|
|
if ((query & VirtualFunctions) && (f->isFinal() || f->isSignal() || f->isStatic())) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal())) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & NonStaticFunctions) && (f->isStatic())) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & NonEmptyFunctions) && (f->isEmptyFunction())) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & NormalFunctions) && (f->isSignal())) {
|
|
continue;
|
|
}
|
|
|
|
if ((query & AbstractFunctions) && !f->isAbstract()) {
|
|
continue;
|
|
}
|
|
|
|
functions << f;
|
|
}
|
|
|
|
// qDebug() << "queried" << m_type_entry->qualifiedCppName() << "got" << functions.size() << "out of" << m_functions.size();
|
|
|
|
return functions;
|
|
}
|
|
|
|
|
|
bool AbstractMetaClass::hasInconsistentFunctions() const
|
|
{
|
|
return cppInconsistentFunctions().size() > 0;
|
|
}
|
|
|
|
bool AbstractMetaClass::hasSignals() const
|
|
{
|
|
return cppSignalFunctions().size() > 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Adds the specified interface to this class by adding all the
|
|
* functions in the interface to this class.
|
|
*/
|
|
void AbstractMetaClass::addInterface(AbstractMetaClass *interface)
|
|
{
|
|
Q_ASSERT(!m_interfaces.contains(interface));
|
|
m_interfaces << interface;
|
|
|
|
if (m_extracted_interface != 0 && m_extracted_interface != interface)
|
|
m_extracted_interface->addInterface(interface);
|
|
|
|
foreach (AbstractMetaFunction *function, interface->functions())
|
|
if (!hasFunction(function) && !function->isConstructor()) {
|
|
AbstractMetaFunction *cpy = function->copy();
|
|
// We do not want this in PythonQt:
|
|
//cpy->setImplementingClass(this);
|
|
|
|
// Setup that this function is an interface class.
|
|
cpy->setInterfaceClass(interface);
|
|
*cpy += AbstractMetaAttributes::InterfaceFunction;
|
|
|
|
// Copy the modifications in interface into the implementing classes.
|
|
FunctionModificationList mods = function->modifications(interface);
|
|
foreach (const FunctionModification &mod, mods) {
|
|
m_type_entry->addFunctionModification(mod);
|
|
}
|
|
|
|
// It should be mostly safe to assume that when we implement an interface
|
|
// we don't "pass on" pure virtual functions to our sublcasses...
|
|
// *cpy -= AbstractMetaAttributes::Abstract;
|
|
|
|
addFunction(cpy);
|
|
}
|
|
}
|
|
|
|
|
|
void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces)
|
|
{
|
|
m_interfaces = interfaces;
|
|
}
|
|
|
|
|
|
AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName)
|
|
{
|
|
foreach (AbstractMetaEnum *e, m_enums) {
|
|
if (e->name() == enumName)
|
|
return e;
|
|
}
|
|
|
|
if (typeEntry()->designatedInterface())
|
|
return extractInterface()->findEnum(enumName);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! Recursivly searches for the enum value named \a enumValueName in
|
|
this class and its superclasses and interfaces. Values belonging to
|
|
\a meta_enum are excluded from the search.
|
|
*/
|
|
AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValueName, AbstractMetaEnum *meta_enum)
|
|
{
|
|
foreach (AbstractMetaEnum *e, m_enums) {
|
|
if (e == meta_enum)
|
|
continue;
|
|
foreach (AbstractMetaEnumValue *v, e->values()) {
|
|
if (v->name() == enumValueName)
|
|
return v;
|
|
}
|
|
}
|
|
|
|
if (typeEntry()->designatedInterface())
|
|
return extractInterface()->findEnumValue(enumValueName, meta_enum);
|
|
|
|
if (baseClass() != 0)
|
|
return baseClass()->findEnumValue(enumValueName, meta_enum);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*!
|
|
* Searches through all of this class' enums for a value matching the
|
|
* name \a enumValueName. The name is excluding the class/namespace
|
|
* prefix. The function recursivly searches interfaces and baseclasses
|
|
* of this class.
|
|
*/
|
|
AbstractMetaEnum *AbstractMetaClass::findEnumForValue(const QString &enumValueName)
|
|
{
|
|
foreach (AbstractMetaEnum *e, m_enums) {
|
|
foreach (AbstractMetaEnumValue *v, e->values()) {
|
|
if (v->name() == enumValueName)
|
|
return e;
|
|
}
|
|
}
|
|
|
|
if (typeEntry()->designatedInterface())
|
|
return extractInterface()->findEnumForValue(enumValueName);
|
|
|
|
if (baseClass() != 0)
|
|
return baseClass()->findEnumForValue(enumValueName);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void add_extra_include_for_type(AbstractMetaClass *meta_class, const AbstractMetaType *type)
|
|
{
|
|
|
|
if (type == 0)
|
|
return;
|
|
|
|
Q_ASSERT(meta_class != 0);
|
|
const TypeEntry *entry = (type ? type->typeEntry() : 0);
|
|
if (entry != 0 && entry->isComplex()) {
|
|
const ComplexTypeEntry *centry = static_cast<const ComplexTypeEntry *>(entry);
|
|
ComplexTypeEntry *class_entry = meta_class->typeEntry();
|
|
if (class_entry != 0 && centry->include().isValid())
|
|
class_entry->addExtraInclude(centry->include());
|
|
}
|
|
|
|
if (type->hasInstantiations()) {
|
|
QList<AbstractMetaType *> instantiations = type->instantiations();
|
|
foreach (AbstractMetaType *instantiation, instantiations)
|
|
add_extra_include_for_type(meta_class, instantiation);
|
|
}
|
|
}
|
|
|
|
static void add_extra_includes_for_function(AbstractMetaClass *meta_class, const AbstractMetaFunction *meta_function)
|
|
{
|
|
Q_ASSERT(meta_class != 0);
|
|
Q_ASSERT(meta_function != 0);
|
|
add_extra_include_for_type(meta_class, meta_function->type());
|
|
|
|
AbstractMetaArgumentList arguments = meta_function->arguments();
|
|
foreach (AbstractMetaArgument *argument, arguments)
|
|
add_extra_include_for_type(meta_class, argument->type());
|
|
}
|
|
|
|
void AbstractMetaClass::fixFunctions()
|
|
{
|
|
if (m_functions_fixed)
|
|
return;
|
|
else
|
|
m_functions_fixed = true;
|
|
|
|
AbstractMetaClass *super_class = baseClass();
|
|
AbstractMetaFunctionList funcs = functions();
|
|
|
|
// printf("fix functions for %s\n", qPrintable(name()));
|
|
|
|
if (super_class != 0)
|
|
super_class->fixFunctions();
|
|
int iface_idx = 0;
|
|
while (super_class || iface_idx < interfaces().size()) {
|
|
// printf(" - base: %s\n", qPrintable(super_class->name()));
|
|
|
|
// Since we always traverse the complete hierarchy we are only
|
|
// interrested in what each super class implements, not what
|
|
// we may have propagated from their base classes again.
|
|
AbstractMetaFunctionList super_funcs;
|
|
if (super_class) {
|
|
|
|
// Super classes can never be final
|
|
if (super_class->isFinalInTargetLang()) {
|
|
ReportHandler::warning("Final class '" + super_class->name() + "' set to non-final, as it is extended by other classes");
|
|
*super_class -= AbstractMetaAttributes::FinalInTargetLang;
|
|
}
|
|
super_funcs = super_class->queryFunctions(AbstractMetaClass::ClassImplements);
|
|
} else {
|
|
super_funcs = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::NormalFunctions);
|
|
}
|
|
|
|
QSet<AbstractMetaFunction *> funcs_to_add;
|
|
for (int sfi=0; sfi<super_funcs.size(); ++sfi) {
|
|
AbstractMetaFunction *sf = super_funcs.at(sfi);
|
|
|
|
if (sf->isRemovedFromAllLanguages(sf->implementingClass()))
|
|
continue;
|
|
|
|
// we generally don't care about private functions, but we have to get the ones that are
|
|
// virtual in case they override abstract functions.
|
|
bool add = (sf->isNormal() || sf->isSignal() || sf->isEmptyFunction());
|
|
for (int fi=0; fi<funcs.size(); ++fi) {
|
|
AbstractMetaFunction *f = funcs.at(fi);
|
|
if (f->isRemovedFromAllLanguages(f->implementingClass()))
|
|
continue;
|
|
|
|
uint cmp = f->compareTo(sf);
|
|
|
|
if (cmp & AbstractMetaFunction::EqualModifiedName) {
|
|
// printf(" - %s::%s similar to %s::%s %x vs %x\n",
|
|
// qPrintable(sf->implementingClass()->typeEntry()->qualifiedCppName()),
|
|
// qPrintable(sf->name()),
|
|
// qPrintable(f->implementingClass()->typeEntry()->qualifiedCppName()),
|
|
// qPrintable(f->name()),
|
|
// sf->attributes(),
|
|
// f->attributes());
|
|
|
|
add = false;
|
|
if (cmp & AbstractMetaFunction::EqualArguments) {
|
|
|
|
// if (!(cmp & AbstractMetaFunction::EqualReturnType)) {
|
|
// ReportHandler::warning(QString("%1::%2 and %3::%4 differ in retur type")
|
|
// .arg(sf->implementingClass()->name())
|
|
// .arg(sf->name())
|
|
// .arg(f->implementingClass()->name())
|
|
// .arg(f->name()));
|
|
// }
|
|
|
|
// Same function, propegate virtual...
|
|
if (!(cmp & AbstractMetaFunction::EqualAttributes)) {
|
|
if (!f->isEmptyFunction()) {
|
|
if (!sf->isFinalInCpp() && f->isFinalInCpp()) {
|
|
*f -= AbstractMetaAttributes::FinalInCpp;
|
|
// printf(" --- inherit virtual\n");
|
|
}
|
|
if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) {
|
|
*f -= AbstractMetaAttributes::FinalInTargetLang;
|
|
// printf(" --- inherit virtual\n");
|
|
}
|
|
if (!f->isFinalInTargetLang() && f->isPrivate()) {
|
|
f->setFunctionType(AbstractMetaFunction::EmptyFunction);
|
|
f->setVisibility(AbstractMetaAttributes::Protected);
|
|
*f += AbstractMetaAttributes::FinalInTargetLang;
|
|
ReportHandler::warning(QString("private virtual function '%1' in '%2'")
|
|
.arg(f->signature())
|
|
.arg(f->implementingClass()->name()));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (f->visibility() != sf->visibility()) {
|
|
QString warn = QString("visibility of function '%1' modified in class '%2'")
|
|
.arg(f->name()).arg(name());
|
|
ReportHandler::warning(warn);
|
|
|
|
// If new visibility is private, we can't
|
|
// do anything. If it isn't, then we
|
|
// prefer the parent class's visibility
|
|
// setting for the function.
|
|
if (!f->isPrivate() && !sf->isPrivate())
|
|
f->setVisibility(sf->visibility());
|
|
|
|
// Private overrides of abstract functions have to go into the class or
|
|
// the subclasses will not compile as non-abstract classes.
|
|
// But they don't need to be implemented, since they can never be called.
|
|
if (f->isPrivate() && sf->isAbstract()) {
|
|
f->setFunctionType(AbstractMetaFunction::EmptyFunction);
|
|
f->setVisibility(sf->visibility());
|
|
*f += AbstractMetaAttributes::FinalInTargetLang;
|
|
*f += AbstractMetaAttributes::FinalInCpp;
|
|
}
|
|
}
|
|
|
|
// Set the class which first declares this function, afawk
|
|
f->setDeclaringClass(sf->declaringClass());
|
|
|
|
if (sf->isFinalInTargetLang() && !sf->isPrivate() && !f->isPrivate() && !sf->isStatic() && !f->isStatic()) {
|
|
// Shadowed funcion, need to make base class
|
|
// function non-virtual
|
|
if (f->implementingClass() != sf->implementingClass() && f->implementingClass()->inheritsFrom(sf->implementingClass())) {
|
|
|
|
// Check whether the superclass method has been redefined to non-final
|
|
|
|
bool hasNonFinalModifier = false;
|
|
bool isBaseImplPrivate = false;
|
|
FunctionModificationList mods = sf->modifications(sf->implementingClass());
|
|
foreach (FunctionModification mod, mods) {
|
|
if (mod.isNonFinal()) {
|
|
hasNonFinalModifier = true;
|
|
break;
|
|
} else if (mod.isPrivate()) {
|
|
isBaseImplPrivate = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!hasNonFinalModifier && !isBaseImplPrivate) {
|
|
ReportHandler::warning(QString::fromLatin1("Shadowing: %1::%2 and %3::%4; Java code will not compile")
|
|
.arg(sf->implementingClass()->name())
|
|
.arg(sf->signature())
|
|
.arg(f->implementingClass()->name())
|
|
.arg(f->signature()));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) {
|
|
AbstractMetaArgumentList arguments;
|
|
if (f->arguments().size() < sf->arguments().size())
|
|
arguments = sf->arguments();
|
|
else
|
|
arguments = f->arguments();
|
|
|
|
for (int i=0; i<arguments.size(); ++i)
|
|
arguments[i]->setDefaultValueExpression(QString());
|
|
}
|
|
|
|
|
|
// Otherwise we have function shadowing and we can
|
|
// skip the thing...
|
|
} else if (cmp & AbstractMetaFunction::EqualName && !sf->isSignal()) {
|
|
|
|
// In the case of function shadowing where the function name has been altered to
|
|
// avoid conflict, we don't copy in the original.
|
|
add = false;
|
|
}
|
|
|
|
}
|
|
|
|
if (add)
|
|
funcs_to_add << sf;
|
|
}
|
|
|
|
foreach (AbstractMetaFunction *f, funcs_to_add)
|
|
funcs << f->copy();
|
|
|
|
if (super_class)
|
|
super_class = super_class->baseClass();
|
|
else
|
|
iface_idx++;
|
|
}
|
|
|
|
bool hasPrivateConstructors = false;
|
|
bool hasPublicConstructors = false;
|
|
foreach (AbstractMetaFunction *func, funcs) {
|
|
FunctionModificationList mods = func->modifications(this);
|
|
foreach (const FunctionModification &mod, mods) {
|
|
if (mod.isRenameModifier()) {
|
|
// qDebug() << name() << func->originalName() << func << " from "
|
|
// << func->implementingClass()->name() << "renamed to" << mod.renamedTo();
|
|
func->setName(mod.renamedTo());
|
|
}
|
|
}
|
|
|
|
// Make sure class is abstract if one of the functions is
|
|
if (func->isAbstract()) {
|
|
(*this) += AbstractMetaAttributes::Abstract;
|
|
(*this) -= AbstractMetaAttributes::Final;
|
|
}
|
|
|
|
if (func->isConstructor()) {
|
|
if (func->isPrivate())
|
|
hasPrivateConstructors = true;
|
|
else
|
|
hasPublicConstructors = true;
|
|
}
|
|
|
|
|
|
|
|
// Make sure that we include files for all classes that are in use
|
|
|
|
if (!func->isRemovedFrom(this, TypeSystem::ShellCode))
|
|
add_extra_includes_for_function(this, func);
|
|
}
|
|
|
|
if (hasPrivateConstructors && !hasPublicConstructors) {
|
|
(*this) += AbstractMetaAttributes::Abstract;
|
|
(*this) -= AbstractMetaAttributes::Final;
|
|
}
|
|
|
|
foreach (AbstractMetaFunction *f1, funcs) {
|
|
foreach (AbstractMetaFunction *f2, funcs) {
|
|
if (f1 != f2) {
|
|
uint cmp = f1->compareTo(f2);
|
|
if ((cmp & AbstractMetaFunction::EqualName)
|
|
&& !f1->isFinalInCpp()
|
|
&& f2->isFinalInCpp()) {
|
|
*f2 += AbstractMetaAttributes::FinalOverload;
|
|
// qDebug() << f2 << f2->implementingClass()->name() << "::" << f2->name() << f2->arguments().size() << " vs " << f1 << f1->implementingClass()->name() << "::" << f1->name() << f1->arguments().size();
|
|
// qDebug() << " " << f2;
|
|
// AbstractMetaArgumentList f2Args = f2->arguments();
|
|
// foreach (AbstractMetaArgument *a, f2Args)
|
|
// qDebug() << " " << a->type()->name() << a->name();
|
|
// qDebug() << " " << f1;
|
|
// AbstractMetaArgumentList f1Args = f1->arguments();
|
|
// foreach (AbstractMetaArgument *a, f1Args)
|
|
// qDebug() << " " << a->type()->name() << a->name();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
setFunctions(funcs);
|
|
}
|
|
|
|
|
|
QString AbstractMetaType::minimalSignature() const
|
|
{
|
|
QString minimalSignature;
|
|
if (isConstant())
|
|
minimalSignature += "const ";
|
|
minimalSignature += typeEntry()->qualifiedCppName();
|
|
if (hasInstantiations()) {
|
|
QList<AbstractMetaType *> instantiations = this->instantiations();
|
|
minimalSignature += "<";
|
|
for (int i=0;i<instantiations.size();++i) {
|
|
if (i > 0)
|
|
minimalSignature += ",";
|
|
minimalSignature += instantiations.at(i)->minimalSignature();
|
|
}
|
|
minimalSignature += ">";
|
|
}
|
|
|
|
if (isReference())
|
|
minimalSignature += "&";
|
|
for (int j=0; j<indirections(); ++j)
|
|
minimalSignature += "*";
|
|
|
|
return minimalSignature;
|
|
}
|
|
|
|
bool AbstractMetaType::hasNativeId() const
|
|
{
|
|
return (isQObject() || isValue() || isObject()) && typeEntry()->isNativeIdBased();
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* Other stuff...
|
|
*/
|
|
|
|
|
|
AbstractMetaEnum *AbstractMetaClassList::findEnum(const EnumTypeEntry *entry) const
|
|
{
|
|
Q_ASSERT(entry->isEnum());
|
|
|
|
QString qualified_name = entry->qualifiedCppName();
|
|
int pos = qualified_name.lastIndexOf("::");
|
|
|
|
QString enum_name;
|
|
QString class_name;
|
|
|
|
if (pos > 0) {
|
|
enum_name = qualified_name.mid(pos + 2);
|
|
class_name = qualified_name.mid(0, pos);
|
|
} else {
|
|
enum_name = qualified_name;
|
|
class_name = TypeDatabase::globalNamespaceClassName(entry);
|
|
}
|
|
|
|
AbstractMetaClass *meta_class = findClass(class_name);
|
|
if (!meta_class) {
|
|
ReportHandler::warning(QString("AbstractMeta::findEnum(), unknown class '%1' in '%2'")
|
|
.arg(class_name).arg(entry->qualifiedCppName()));
|
|
return 0;
|
|
}
|
|
|
|
return meta_class->findEnum(enum_name);
|
|
}
|
|
|
|
AbstractMetaEnumValue *AbstractMetaEnumValueList::find(const QString &name) const
|
|
{
|
|
for (int i=0; i<size(); ++i) {
|
|
if (name == at(i)->name())
|
|
return at(i);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
AbstractMetaEnumValue *AbstractMetaClassList::findEnumValue(const QString &name) const
|
|
{
|
|
QStringList lst = name.split(QLatin1String("::"));
|
|
|
|
Q_ASSERT_X(lst.size() == 2, "AbstractMetaClassList::findEnumValue()", "Expected qualified enum");
|
|
|
|
|
|
QString prefixName = lst.at(0);
|
|
QString enumName = lst.at(1);
|
|
|
|
AbstractMetaClass *cl = findClass(prefixName);
|
|
if (cl)
|
|
return cl->findEnumValue(enumName, 0);
|
|
|
|
ReportHandler::warning(QString("no matching enum '%1'").arg(name));
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* Searches the list after a class that mathces \a name; either as
|
|
* C++, Java base name or complete Java package.class name.
|
|
*/
|
|
|
|
AbstractMetaClass *AbstractMetaClassList::findClass(const QString &name) const
|
|
{
|
|
if (name.isEmpty())
|
|
return 0;
|
|
|
|
foreach (AbstractMetaClass *c, *this) {
|
|
if (c->qualifiedCppName() == name)
|
|
return c;
|
|
}
|
|
|
|
foreach (AbstractMetaClass *c, *this) {
|
|
if (c->fullName() == name)
|
|
return c;
|
|
}
|
|
|
|
foreach (AbstractMetaClass *c, *this) {
|
|
if (c->name() == name)
|
|
return c;
|
|
}
|
|
|
|
return 0;
|
|
}
|