From e79b99edca1a8d38b81c929934ec4093c1292e74 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 18 Sep 2017 13:56:03 +0200 Subject: CodeModel: Handle access of inherited classes Store the access of the base class in the code model. Remove protected/private base classes in the abstract meta builder as otherwise invalid code will be generated for classes like QAbstract3DGraph : public QWindow, protected QOpenGLFunctions when the protected hack is not in use (on Windows). Task-number: PYSIDE-487 Change-Id: I5bc2dad16f903da86e6e41450c2f9a76726ac028 Reviewed-by: Christian Tismer --- .../shiboken2/ApiExtractor/abstractmetabuilder.cpp | 28 ++++++++++++------- sources/shiboken2/ApiExtractor/abstractmetalang.h | 6 +++++ .../ApiExtractor/clangparser/clangbuilder.cpp | 5 ++-- .../shiboken2/ApiExtractor/parser/codemodel.cpp | 31 ++++++++++++---------- sources/shiboken2/ApiExtractor/parser/codemodel.h | 13 ++++++--- 5 files changed, 53 insertions(+), 30 deletions(-) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index b235d9bd9..3d2afd8bf 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -1284,7 +1284,15 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem AbstractMetaClass *metaClass = q->createMetaClass(); metaClass->setTypeEntry(type); - metaClass->setBaseClassNames(classItem->baseClasses()); + + QStringList baseClassNames; + const QVector<_ClassModelItem::BaseClass> &baseClasses = classItem->baseClasses(); + for (const _ClassModelItem::BaseClass &baseClass : baseClasses) { + if (baseClass.accessPolicy == CodeModel::Public) + baseClassNames.append(baseClass.name); + } + + metaClass->setBaseClassNames(baseClassNames); *metaClass += AbstractMetaAttributes::Public; if (type->stream()) metaClass->setStream(true); @@ -2877,19 +2885,19 @@ bool AbstractMetaBuilderPrivate::isQObject(const FileModelItem &dom, const QStri classItem = ns->findClass(names.at(names.size() - 1)); } - bool isqobject = classItem && classItem->extendsClass(QLatin1String("QObject")); + if (classItem == nullptr) + return false; - if (classItem && !isqobject) { - QStringList baseClasses = classItem->baseClasses(); - for (int i = 0; i < baseClasses.count(); ++i) { + if (classItem->extendsClass(QLatin1String("QObject"))) + return true; - isqobject = isQObject(dom, baseClasses.at(i)); - if (isqobject) - break; - } + const QVector<_ClassModelItem::BaseClass> &baseClasses = classItem->baseClasses(); + for (const _ClassModelItem::BaseClass &baseClass : baseClasses) { + if (isQObject(dom, baseClass.name)) + return true; } - return isqobject; + return false; } diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 0529bed24..2643ac0ed 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -1417,6 +1417,12 @@ public: Q_DECLARE_FLAGS(OperatorQueryOptions, OperatorQueryOption) Q_FLAG(OperatorQueryOption) + struct BaseClass + { + QString name; + int access = Public; + }; + AbstractMetaClass() : m_hasVirtuals(false), m_isPolymorphic(false), diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index ea6559689..73b1638ef 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -444,10 +444,11 @@ void BuilderPrivate::addBaseClass(const CXCursor &cursor) QString baseClassName = getTypeName(inheritedType); // use type. const CXCursor declCursor = clang_getTypeDeclaration(inheritedType); const CursorClassHash::const_iterator it = m_cursorClassHash.constFind(declCursor); + const CodeModel::AccessPolicy access = accessPolicy(clang_getCXXAccessSpecifier(cursor)); if (it == m_cursorClassHash.constEnd()) { // Set unqualified name. This happens in cases like "class X : public std::list<...>" // "template class Foo : public T" and standard types like true_type, false_type. - m_currentClass->setBaseClasses(m_currentClass->baseClasses() << baseClassName); + m_currentClass->addBaseClass(baseClassName, access); return; } // Completely qualify the class name by looking it up and taking its scope @@ -468,7 +469,7 @@ void BuilderPrivate::addBaseClass(const CXCursor &cursor) baseClassName.prepend(colonColon()); baseClassName.prepend(baseScope.join(colonColon())); } - m_currentClass->setBaseClasses(m_currentClass->baseClasses() << baseClassName); + m_currentClass->addBaseClass(baseClassName, access); } static inline CXCursor definitionFromTypeRef(const CXCursor &typeRefCursor) diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index 667e27344..7c3bbbede 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -514,16 +514,6 @@ _ClassModelItem::~_ClassModelItem() { } -QStringList _ClassModelItem::baseClasses() const -{ - return m_baseClasses; -} - -void _ClassModelItem::setBaseClasses(const QStringList &baseClasses) -{ - m_baseClasses = baseClasses; -} - TemplateParameterList _ClassModelItem::templateParameters() const { return m_templateParameters; @@ -534,14 +524,21 @@ void _ClassModelItem::setTemplateParameters(const TemplateParameterList &templat m_templateParameters = templateParameters; } -void _ClassModelItem::addBaseClass(const QString &baseClass) +void _ClassModelItem::addBaseClass(const QString &name, CodeModel::AccessPolicy accessPolicy) { + _ClassModelItem::BaseClass baseClass; + baseClass.name = name; + baseClass.accessPolicy = accessPolicy; m_baseClasses.append(baseClass); } bool _ClassModelItem::extendsClass(const QString &name) const { - return m_baseClasses.contains(name); + for (const BaseClass &bc : m_baseClasses) { + if (bc.name == name) + return true; + } + return false; } void _ClassModelItem::setClassType(CodeModel::ClassType type) @@ -578,8 +575,14 @@ static void formatModelItemList(QDebug &d, const char *prefix, const List &l, void _ClassModelItem::formatDebug(QDebug &d) const { _CodeModelItem::formatDebug(d); - if (!m_baseClasses.isEmpty()) - d << ", inherits=" << m_baseClasses; + if (!m_baseClasses.isEmpty()) { + d << ", inherits="; + for (int i = 0, size = m_baseClasses.size(); i < size; ++i) { + if (i) + d << ", "; + d << m_baseClasses.at(i).name << " (" << m_baseClasses.at(i).accessPolicy << ')'; + } + } formatModelItemList(d, ", templateParameters=", m_templateParameters); formatScopeItemsDebug(d); } diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index 4d6bfd06a..fd17b442c 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -349,16 +349,21 @@ class _ClassModelItem: public _ScopeModelItem public: DECLARE_MODEL_NODE(Class) + struct BaseClass + { + QString name; + CodeModel::AccessPolicy accessPolicy = CodeModel::Public; + }; + explicit _ClassModelItem(CodeModel *model, int kind = __node_kind) : _ScopeModelItem(model, kind), m_classType(CodeModel::Class) {} explicit _ClassModelItem(CodeModel *model, const QString &name, int kind = __node_kind) : _ScopeModelItem(model, name, kind), m_classType(CodeModel::Class) {} ~_ClassModelItem(); - QStringList baseClasses() const; + QVector baseClasses() const { return m_baseClasses; } - void setBaseClasses(const QStringList &baseClasses); - void addBaseClass(const QString &baseClass); + void addBaseClass(const QString &name, CodeModel::AccessPolicy accessPolicy); TemplateParameterList templateParameters() const; void setTemplateParameters(const TemplateParameterList &templateParameters); @@ -376,7 +381,7 @@ public: #endif private: - QStringList m_baseClasses; + QVector m_baseClasses; TemplateParameterList m_templateParameters; CodeModel::ClassType m_classType; -- cgit v1.2.3