[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-bindings
Subject: [Kde-bindings] KDE/kdebindings/generator/generators/smoke
From: Arno Rehn <kde () arnorehn ! de>
Date: 2009-11-02 19:56:33
Message-ID: 1257191793.740302.27045.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 1043990 by arnorehn:
Fix inherited virtual methods not showing up in the methods table.
CCMAIL: kde-bindings@kde.org
M +5 -0 globals.h
M +93 -0 helpers.cpp
M +2 -77 writeClasses.cpp
M +36 -6 writeSmokeDataFile.cpp
--- trunk/KDE/kdebindings/generator/generators/smoke/globals.h #1043989:1043990
@@ -75,6 +75,7 @@
QSet<Class*> externalClasses;
QSet<Type*> usedTypes;
QStringList includedClasses;
+ QHash<const Class*, QSet<const Method*> > declaredVirtualMethods;
};
struct SmokeClassFiles
@@ -97,6 +98,9 @@
struct Util
{
+ typedef QPair<const Method*, QString> MethodStringPair;
+ typedef QList<MethodStringPair> VirtualMethodList;
+
static QHash<QString, QString> typeMap;
static QHash<const Method*, const Function*> globalFunctionMap;
static QHash<const Method*, const Field*> fieldAccessors;
@@ -127,6 +131,7 @@
static QString assignmentString(const Type* type, const QString& var);
static QList<const Method*> collectVirtualMethods(const Class* klass);
static const Method* isVirtualOverriden(const Method& meth, const Class* klass);
+ static VirtualMethodList virtualMethodsForClass(const Class* klass);
};
#endif
--- trunk/KDE/kdebindings/generator/generators/smoke/helpers.cpp #1043989:1043990
@@ -646,6 +646,99 @@
return 0;
}
+Util::VirtualMethodList Util::virtualMethodsForClass(const Class* klass)
+{
+ static QHash<const Class*, Util::VirtualMethodList > cache;
+
+ // virtual method callbacks for classes that can't be instanciated aren't useful
+ if (!Util::canClassBeInstanciated(klass))
+ return Util::VirtualMethodList();
+
+ if (cache.contains(klass))
+ return cache[klass];
+
+ Util::VirtualMethodList ret;
+
+ QSet<QString> virtMeths; // virtual methods that already have been taken care \
of + QList<const Method*> pureVirtuals;
+ foreach (const Method& meth, klass->methods()) {
+ // if there are default parameters, it's not the 'original' method.. skip it
+ if (!meth.remainingDefaultValues().isEmpty())
+ continue;
+ // first, generate all virtual methods of this class. inherited ones come \
after that. + if (((meth.flags() & Method::Virtual) || (meth.flags() & \
Method::PureVirtual)) && !meth.isDestructor()) { + if (meth.access() != \
Access_private) { + ret << qMakePair(&meth, klass->toString());
+ }
+ virtMeths.insert(meth.toString(false, false, false));
+ }
+ }
+
+ QList<const Method*> inheritedVirtuals;
+ foreach (const Class::BaseClassSpecifier& bspec, klass->baseClasses()) {
+ // now collect all virtual methods of the base classes
+ inheritedVirtuals += Util::collectVirtualMethods(bspec.baseClass);
+ }
+
+ foreach (const Method* meth, inheritedVirtuals) {
+ if (!meth->remainingDefaultValues().isEmpty())
+ continue;
+ if (meth->flags() & Method::PureVirtual) {
+ // postpone pure virtuals to see if they have been overridden
+ pureVirtuals << meth;
+ continue;
+ }
+
+ QString methString = meth->toString(false, false, false);
+ if (virtMeths.contains(methString))
+ continue;
+ const Method *m = 0;
+ if ((m = Util::isVirtualOverriden(*meth, klass)) && m->access() == \
Access_private) { + // if the method was overriden and put under private \
access, skip it. + virtMeths.insert(methString);
+ continue;
+ }
+ /* If the method was overridden, use the overriding method for getting the \
classname - else use the virtual method itself + Don't use className here, \
as this won't work with hidden methods. Imagine: +
+ struct A {
+ virtual void foo() {}
+ };
+
+ struct B : public A {
+ virtual void foo(int) {}
+ };
+
+ B::foo(int) hides A::foo(). So if we have an instance of B, we can't \
call this->B::foo(), but have to use this->A::foo() + */
+ ret << qMakePair(meth, m ? m->getClass()->toString() : \
meth->getClass()->toString()); + virtMeths.insert(methString);
+ }
+ foreach (const Method* meth, pureVirtuals) {
+ QString methString = meth->toString(false, false, false);
+ // Check if the pure virtual was overriden somewhere - then we shouldn't \
generate a callback with the pure virtual flag set + // (as it isn't, \
anymore). + // If the overriding method was declared virtual, too, we find it \
in virtMeths. Then it's already generated and we can continue. + // If it \
hasn't, we have to go looking for it. If we find it, generate a normal virtual method \
for it. + if (virtMeths.contains(methString))
+ continue;
+ const Method* m = 0;
+ if ((m = Util::isVirtualOverriden(*meth, klass))) {
+ if (m->access() != Access_private) {
+ ret << qMakePair(m, klass->toString());
+ }
+ virtMeths.insert(methString);
+ } else {
+ // we didn't find any overriding method - generate a pure virtual one
+ ret << qMakePair(meth, klass->toString());
+ virtMeths.insert(methString);
+ }
+ }
+
+ cache[klass] = ret;
+ return ret;
+}
+
bool Options::typeExcluded(const QString& typeName)
{
foreach (const QRegExp& exp, Options::excludeExpressions) {
--- trunk/KDE/kdebindings/generator/generators/smoke/writeClasses.cpp \
#1043989:1043990 @@ -409,83 +409,8 @@
enumOut << " break;\n";
}
- // virtual method callbacks for classes that can't be instanciated aren't useful
- if (Util::canClassBeInstanciated(klass)) {
- QSet<QString> virtMeths; // virtual methods that already have been taken \
care of
- QList<const Method*> pureVirtuals;
- foreach (const Method& meth, klass->methods()) {
- // if there are default parameters, it's not the 'original' method.. \
skip it
- if (!meth.remainingDefaultValues().isEmpty())
- continue;
- // first, generate all virtual methods of this class. inherited ones \
come after that.
- if (((meth.flags() & Method::Virtual) || (meth.flags() & \
Method::PureVirtual)) && !meth.isDestructor()) {
- if (meth.access() != Access_private) {
- generateVirtualMethod(out, className, meth, includes);
- }
- virtMeths.insert(meth.toString(false, false, false));
- }
- }
-
- QList<const Method*> inheritedVirtuals;
- foreach (const Class::BaseClassSpecifier& bspec, klass->baseClasses()) {
- // now collect all virtual methods of the base classes
- inheritedVirtuals += Util::collectVirtualMethods(bspec.baseClass);
- }
-
- foreach (const Method* meth, inheritedVirtuals) {
- if (!meth->remainingDefaultValues().isEmpty())
- continue;
- if (meth->flags() & Method::PureVirtual) {
- // postpone pure virtuals to see if they have been overridden
- pureVirtuals << meth;
- continue;
- }
-
- QString methString = meth->toString(false, false, false);
- if (virtMeths.contains(methString))
- continue;
- const Method *m = 0;
- if ((m = Util::isVirtualOverriden(*meth, klass)) && m->access() == \
Access_private) {
- // if the method was overriden and put under private access, skip \
it.
- virtMeths.insert(methString);
- continue;
- }
- /* If the method was overridden, use the overriding method for getting \
the classname - else use the virtual method itself
- Don't use className here, as this won't work with hidden methods. \
Imagine:
-
- struct A {
- virtual void foo() {}
- };
-
- struct B : public A {
- virtual void foo(int) {}
- };
-
- B::foo(int) hides A::foo(). So if we have an instance of B, we can't \
call this->B::foo(), but have to use this->A::foo()
- */
- generateVirtualMethod(out, m ? m->getClass()->toString() : \
meth->getClass()->toString(), *meth, includes);
- virtMeths.insert(methString);
- }
- foreach (const Method* meth, pureVirtuals) {
- QString methString = meth->toString(false, false, false);
- // Check if the pure virtual was overriden somewhere - then we shouldn't \
generate a callback with the pure virtual flag set
- // (as it isn't, anymore).
- // If the overriding method was declared virtual, too, we find it in \
virtMeths. Then it's already generated and we can continue.
- // If it hasn't, we have to go looking for it. If we find it, generate a \
normal virtual method for it.
- if (virtMeths.contains(methString))
- continue;
- const Method* m = 0;
- if ((m = Util::isVirtualOverriden(*meth, klass))) {
- if (m->access() != Access_private) {
- generateVirtualMethod(out, className, *m, includes);
- }
- virtMeths.insert(methString);
- } else {
- // we didn't find any overriding method - generate a pure virtual \
one
- generateVirtualMethod(out, className, *meth, includes);
- virtMeths.insert(methString);
- }
- }
+ foreach (const Util::MethodStringPair& pair, \
Util::virtualMethodsForClass(klass)) { + generateVirtualMethod(out, \
pair.second, *pair.first, includes); }
// this class contains enums, write out an xenum_operation method
--- trunk/KDE/kdebindings/generator/generators/smoke/writeSmokeDataFile.cpp \
#1043989:1043990 @@ -50,12 +50,30 @@
includedClasses = classIndex.keys();
Util::preparse(&usedTypes, &superClasses, includedClasses); // collect all used \
types, add c'tors.. etc.
+ // Collect the classes that are inherited by classes in this smoke module and \
provide virtual methods. + // These classes need to be indexed as well.
+ foreach (const QString& className, includedClasses) {
+ const Class* klass = &classes[className];
+ Util::VirtualMethodList list = Util::virtualMethodsForClass(klass);
+ foreach (const Util::MethodStringPair& pair, list) {
+ const Method* meth = pair.first;
+ usedTypes << meth->type();
+ foreach (const Parameter& param, meth->parameters()) {
+ usedTypes << param.type();
+ }
+ declaredVirtualMethods[meth->getClass()] << meth;
+ }
+ }
+
// if a class is used somewhere but not listed in the class list, mark it \
external
for (QHash<QString, Class>::iterator iter = ::classes.begin(); iter != \
::classes.end(); iter++) {
if (iter.value().isTemplate() || Options::voidpTypes.contains(iter.key()))
continue;
- if ((isClassUsed(&iter.value()) && iter.value().access() != Access_private) \
|| superClasses.contains(&iter.value())) { + if ( \
(isClassUsed(&iter.value()) && iter.value().access() != Access_private) + \
|| superClasses.contains(&iter.value()) + || \
declaredVirtualMethods.contains(&iter.value())) + {
classIndex[iter.key()] = 1;
if (!Options::classList.contains(iter.key()) || \
iter.value().isForwardDecl()) @@ -344,17 +362,23 @@
currentIdx = 1;
for (QMap<QString, int>::const_iterator iter = classIndex.constBegin(); iter != \
classIndex.constEnd(); iter++) { Class* klass = &classes[iter.key()];
- if (externalClasses.contains(klass))
+ bool isExternal = externalClasses.contains(klass);
+ bool isDeclaredVirtual = declaredVirtualMethods.contains(klass);
+ if (isExternal && !isDeclaredVirtual)
continue;
QMap<QString, QList<const Member*> >& map = classMungedNames[klass];
foreach (const Method& meth, klass->methods()) {
if (meth.access() == Access_private)
continue;
+ if (isExternal && !declaredVirtualMethods[klass].contains(&meth))
+ continue;
methodNames[meth.name()] = 1;
- QString mungedName = Util::mungedName(meth);
- methodNames[mungedName] = 1;
- map[mungedName].append(&meth);
+ if (!isExternal) {
+ QString mungedName = Util::mungedName(meth);
+ methodNames[mungedName] = 1;
+ map[mungedName].append(&meth);
+ }
if (!meth.parameters().count()) {
parameterIndices[&meth] = 0;
@@ -418,10 +442,16 @@
for (QMap<QString, int>::const_iterator iter = classIndex.constBegin(); iter != \
classIndex.constEnd(); iter++) { Class* klass = &classes[iter.key()];
const Method* destructor = 0;
+ bool isExternal = false;
if (externalClasses.contains(klass))
+ isExternal = true;
+ if (isExternal && !declaredVirtualMethods.contains(klass))
continue;
+
int xcall_index = 1;
foreach (const Method& meth, klass->methods()) {
+ if (isExternal && !declaredVirtualMethods[klass].contains(&meth))
+ continue;
if (meth.access() == Access_private)
continue;
if (meth.isDestructor()) {
@@ -458,7 +488,7 @@
} else {
out << ", " << typeIndex[meth.type()];
}
- out << ", " << xcall_index << "},";
+ out << ", " << (isExternal ? 0 : xcall_index) << "},";
// comment
out << "\t//" << i << " " << klass->toString() << "::";
_______________________________________________
Kde-bindings mailing list
Kde-bindings@kde.org
https://mail.kde.org/mailman/listinfo/kde-bindings
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic