1
0
mirror of https://github.com/clementine-player/Clementine synced 2024-12-17 20:09:50 +01:00
Clementine-audio-player-Mac.../3rdparty/pythonqt/generator/abstractmetalang.cpp

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;
}