[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