aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
Diffstat (limited to 'sources')
-rw-r--r--sources/pyside6/PySide6/QtMultimedia/typesystem_multimedia.xml5
-rw-r--r--sources/pyside6/PySide6/glue/qtmultimedia.cpp12
-rw-r--r--sources/pyside6/doc/_tags/android.rst2
-rw-r--r--sources/pyside6/doc/conf.py.in2
-rw-r--r--sources/pyside6/doc/developer/add_port_example.rst6
-rw-r--r--sources/pyside6/doc/developer/pythonversions.md8
-rw-r--r--sources/pyside6/libpyside/signalmanager.cpp14
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp136
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h12
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaenum.cpp15
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaenum.h4
-rw-r--r--sources/shiboken6/ApiExtractor/addedfunction.cpp6
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp24
-rw-r--r--sources/shiboken6/ApiExtractor/classdocumentation.cpp2
-rw-r--r--sources/shiboken6/ApiExtractor/documentation.h1
-rw-r--r--sources/shiboken6/ApiExtractor/enumtypeentry.h12
-rw-r--r--sources/shiboken6/ApiExtractor/messages.cpp4
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.cpp31
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.h13
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel_enums.h10
-rw-r--r--sources/shiboken6/ApiExtractor/parser/typeinfo.cpp39
-rw-r--r--sources/shiboken6/ApiExtractor/parser/typeinfo.h3
-rw-r--r--sources/shiboken6/ApiExtractor/qtdocparser.cpp52
-rw-r--r--sources/shiboken6/ApiExtractor/tests/a.xml2
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp5
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.cpp26
-rw-r--r--sources/shiboken6/doc/typesystem_specifying_types.rst17
-rw-r--r--sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp60
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp31
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator_container.cpp5
-rw-r--r--sources/shiboken6/generator/shiboken/headergenerator.cpp6
-rw-r--r--sources/shiboken6/libshiboken/sbkbindingutils.cpp1
-rw-r--r--sources/shiboken6/libshiboken/sbkmodule.cpp2
-rw-r--r--sources/shiboken6/tests/libsample/functions.h2
-rw-r--r--sources/shiboken6/tests/libsample/samplenamespace.cpp10
-rw-r--r--sources/shiboken6/tests/libsample/samplenamespace.h16
-rw-r--r--sources/shiboken6/tests/samplebinding/namespace_test.py14
-rw-r--r--sources/shiboken6/tests/samplebinding/typesystem_sample.xml5
38 files changed, 466 insertions, 149 deletions
diff --git a/sources/pyside6/PySide6/QtMultimedia/typesystem_multimedia.xml b/sources/pyside6/PySide6/QtMultimedia/typesystem_multimedia.xml
index f62b1ec7d..cbb392761 100644
--- a/sources/pyside6/PySide6/QtMultimedia/typesystem_multimedia.xml
+++ b/sources/pyside6/PySide6/QtMultimedia/typesystem_multimedia.xml
@@ -21,14 +21,9 @@
</namespace-type>
<namespace-type name="QtAudio">
-<!-- FIXME PYSIDE7: Remove namespace "QAudio" and enable the enums.
<enum-type name="Error"/>
<enum-type name="State"/>
<enum-type name="VolumeScale"/>
--->
- <inject-code class="target" position="end"
- file="../glue/qtmultimedia.cpp"
- snippet="qtaudio-namespace-import-enums"/>
<modify-field name="NoError" remove="true"/>
<modify-field name="OpenError" remove="true"/>
<modify-field name="IOError" remove="true"/>
diff --git a/sources/pyside6/PySide6/glue/qtmultimedia.cpp b/sources/pyside6/PySide6/glue/qtmultimedia.cpp
index 65cefa5fc..457621638 100644
--- a/sources/pyside6/PySide6/glue/qtmultimedia.cpp
+++ b/sources/pyside6/PySide6/glue/qtmultimedia.cpp
@@ -26,15 +26,3 @@ const auto size = %CPPSELF.byteCount();
const float result = QtAudio::convertVolume(%1, %2, %3);
%PYARG_0 = %CONVERTTOPYTHON[float](result);
// @snippet qaudio-convertvolume
-
-// @snippet qtaudio-namespace-import-enums
-Shiboken::AutoDecRef qAudio(PyObject_GetAttrString(module, "QAudio"));
-if (!qAudio.isNull()) {
- Shiboken::AutoDecRef qAudioTypeDict(PepType_GetDict(reinterpret_cast<PyTypeObject *>(qAudio.object())));
- Shiboken::AutoDecRef qtAudioTypeDict(PepType_GetDict(pyType));
- for (const auto *oldEnum : {"Error", "State", "VolumeScale"}) {
- if (auto *enumType = PyDict_GetItemString(qAudioTypeDict, oldEnum))
- PyDict_SetItemString(qtAudioTypeDict, oldEnum, enumType);
- }
-}
-// @snippet qtaudio-namespace-import-enums
diff --git a/sources/pyside6/doc/_tags/android.rst b/sources/pyside6/doc/_tags/android.rst
index 0fdf2041a..d694f75f9 100644
--- a/sources/pyside6/doc/_tags/android.rst
+++ b/sources/pyside6/doc/_tags/android.rst
@@ -15,9 +15,9 @@ My tags: Android
../examples/example_multimedia_camera.rst
../examples/example_qml_editingmodel.rst
../examples/example_qml_usingmodel.rst
+ ../examples/example_quick_customitems_painteditem.rst
../examples/example_quick_models_objectlistmodel.rst
../examples/example_quick_models_stringlistmodel.rst
- ../examples/example_quick_painteditem.rst
../examples/example_quickcontrols_contactslist.rst
../examples/example_quickcontrols_gallery.rst
../examples/example_widgets_widgets_digitalclock.rst
diff --git a/sources/pyside6/doc/conf.py.in b/sources/pyside6/doc/conf.py.in
index 5af91019b..38c2c606c 100644
--- a/sources/pyside6/doc/conf.py.in
+++ b/sources/pyside6/doc/conf.py.in
@@ -33,7 +33,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.ifconfig',
'sphinx.ext.graphviz', 'inheritance_diagram', 'pysideinclude',
'sphinx.ext.viewcode',
'sphinx_design', 'sphinx_copybutton', 'myst_parser', 'sphinx_tags',
- 'sphinx_toolbox.decorators', 'sphinx_reredirects']
+ 'sphinx_toolbox.collapse', 'sphinx_toolbox.decorators', 'sphinx_reredirects']
myst_enable_extensions = [
"amsmath",
diff --git a/sources/pyside6/doc/developer/add_port_example.rst b/sources/pyside6/doc/developer/add_port_example.rst
index 59aa2f115..909986e79 100644
--- a/sources/pyside6/doc/developer/add_port_example.rst
+++ b/sources/pyside6/doc/developer/add_port_example.rst
@@ -27,7 +27,13 @@ For example:
$ flake8 --config pyside-setup/.flake8 your_file.py
$ isort your_file.py
+Later on, the tool `tools/sync_examples.py` can be used to update the source
+files from Qt C++. Each difference produced by tool needs to checked with care,
+differences in `qmldir` files (`prefer` directive) might apply to C++ only.
+Also, be careful not to back-port old Qt Widgets Designer `.ui` files with
+unqualified enumerations. If a `.ui` file has additions, make sure to load and
+save it at least once.
Add a new example
-----------------
diff --git a/sources/pyside6/doc/developer/pythonversions.md b/sources/pyside6/doc/developer/pythonversions.md
index a4803bbbe..baef18d77 100644
--- a/sources/pyside6/doc/developer/pythonversions.md
+++ b/sources/pyside6/doc/developer/pythonversions.md
@@ -2,7 +2,8 @@
## Relevant preprocessor defines
-- The version range is determined by `wheel_artifacts/pyproject.toml.base`
+- The version range is determined by `wheel_artifacts/pyproject.toml.base`.
+ This file also defines the version tag (`py_limited_api = "cp310"`).
- `PY_VERSION_HEX` Python version (defined in CPython headers)
- `Py_LIMITED_API` Limited API minimum version, defined in several CMake files
- `PYPY_VERSION` [PyPy](https://pypy.org/) version (defined in PyPy headers)
@@ -16,8 +17,11 @@ The removal of Python versions is tied to their lifetime
- Check the source code for preprocessor defines depending on
values `Py_LIMITED_API`, `PY_VERSION_HEX` and simplify or
remove conditions if possible.
+- Check the usages of `_PepRuntimeVersion()` for outdated versions
- Run the tests and some examples. There might actually
- some version checks in Python code that trigger.
+ some version checks in Python code that trigger
+ (see for example
+ `sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py:70`).
## Adapting to new Python versions
diff --git a/sources/pyside6/libpyside/signalmanager.cpp b/sources/pyside6/libpyside/signalmanager.cpp
index ed7067a2e..d08fb56bf 100644
--- a/sources/pyside6/libpyside/signalmanager.cpp
+++ b/sources/pyside6/libpyside/signalmanager.cpp
@@ -353,6 +353,18 @@ void SignalManager::handleMetaCallError()
Py_SetRecursionLimit(reclimit);
}
+const char *metaObjectCallName(QMetaObject::Call call)
+{
+ static const char *names[] = {
+ "InvokeMetaMethod", "ReadProperty", "WriteProperty", "ResetProperty",
+ "CreateInstance", "IndexOfMethod", "RegisterPropertyMetaType",
+ "RegisterMethodArgumentMetaType", "BindableProperty", "CustomCall",
+ "ConstructInPlace"};
+ constexpr size_t count = sizeof(names)/sizeof(names[0]);
+ static_assert(QMetaObject::ConstructInPlace == count - 1);
+ return call >= 0 && call < count ? names[call] : "<unknown>";
+}
+
// Handler for QMetaObject::ReadProperty/WriteProperty/ResetProperty:
int SignalManagerPrivate::qtPropertyMetacall(QObject *object,
QMetaObject::Call call,
@@ -398,7 +410,7 @@ int SignalManagerPrivate::qtPropertyMetacall(QObject *object,
}
qWarning().noquote().nospace()
- << "An error occurred executing the property metacall " << call
+ << "An error occurred executing the property metacall " << metaObjectCallName(call)
<< " on property \"" << mp.name() << "\" of " << object;
handleMetaCallError(object, &result);
}
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
index ce361245c..9807e1ea6 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
@@ -531,13 +531,22 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
ReportHandler::startProgress("Generated enum model ("
+ QByteArray::number(enums.size()) + ").");
for (const EnumModelItem &item : enums) {
- auto metaEnum = traverseEnum(item, nullptr, QSet<QString>());
+ auto metaEnum = traverseEnum(item, nullptr);
if (metaEnum.has_value()) {
if (metaEnum->typeEntry()->generateCode())
m_globalEnums << metaEnum.value();
}
}
+ const auto &globalTypeDefs = dom->typeDefs();
+ for (const auto &typeDef : globalTypeDefs) {
+ if (typeDef->underlyingTypeCategory() == TypeCategory::Enum) {
+ const auto metaEnum = traverseTypedefedEnum(dom, typeDef, {});
+ if (metaEnum.has_value())
+ m_globalEnums.append(metaEnum.value());
+ }
+ }
+
const auto &namespaceTypeValues = dom->namespaces();
ReportHandler::startProgress("Generated namespace model ("
+ QByteArray::number(namespaceTypeValues.size()) + ").");
@@ -765,7 +774,7 @@ AbstractMetaClassPtr
AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom,
const NamespaceModelItem &namespaceItem)
{
- QString namespaceName = currentScope()->qualifiedName().join(u"::"_s);
+ QString namespaceName = currentScope()->qualifiedNameString();
if (!namespaceName.isEmpty())
namespaceName.append(u"::"_s);
namespaceName.append(namespaceItem->name());
@@ -809,7 +818,7 @@ AbstractMetaClassPtr
m_itemToClass.insert(namespaceItem.get(), metaClass);
}
- traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations());
+ traverseEnums(namespaceItem, metaClass);
pushScope(namespaceItem);
@@ -827,11 +836,20 @@ AbstractMetaClassPtr
// specific typedefs to be used as classes.
const TypeDefList typeDefs = namespaceItem->typeDefs();
for (const TypeDefModelItem &typeDef : typeDefs) {
- const auto cls = traverseTypeDef(dom, typeDef, metaClass);
- if (cls) {
- metaClass->addInnerClass(cls);
- cls->setEnclosingClass(metaClass);
- addAbstractMetaClass(cls, typeDef.get());
+ switch (typeDef->underlyingTypeCategory()) {
+ case TypeCategory::Enum: {
+ const auto metaEnum = traverseTypedefedEnum(dom, typeDef, metaClass);
+ if (metaEnum.has_value())
+ metaClass->addEnum(metaEnum.value());
+ }
+ break;
+ default:
+ if (const auto cls = traverseTypeDef(dom, typeDef, metaClass)) {
+ metaClass->addInnerClass(cls);
+ cls->setEnclosingClass(metaClass);
+ addAbstractMetaClass(cls, typeDef.get());
+ }
+ break;
}
}
@@ -856,16 +874,15 @@ AbstractMetaClassPtr
std::optional<AbstractMetaEnum>
AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &enumItem,
- const AbstractMetaClassPtr &enclosing,
- const QSet<QString> &enumsDeclarations)
+ const AbstractMetaClassPtr &enclosing)
{
- QString qualifiedName = enumItem->qualifiedName().join(u"::"_s);
+ QString qualifiedName = enumItem->qualifiedNameString();
TypeEntryPtr typeEntry;
- const auto enclosingTypeEntry = enclosing ? enclosing->typeEntry() : TypeEntryCPtr{};
if (enumItem->accessPolicy() == Access::Private) {
+ Q_ASSERT(enclosing);
typeEntry = std::make_shared<EnumTypeEntry>(enumItem->qualifiedName().constLast(),
- QVersionNumber(0, 0), enclosingTypeEntry);
+ QVersionNumber(0, 0), enclosing->typeEntry());
TypeDatabase::instance()->addType(typeEntry);
} else if (enumItem->enumKind() != AnonymousEnum) {
typeEntry = TypeDatabase::instance()->findType(qualifiedName);
@@ -881,12 +898,17 @@ std::optional<AbstractMetaEnum>
break;
}
}
+ return createMetaEnum(enumItem, qualifiedName, typeEntry, enclosing);
+}
- QString enumName = enumItem->name();
-
- QString className;
- if (enclosingTypeEntry)
- className = enclosingTypeEntry->qualifiedCppName();
+std::optional<AbstractMetaEnum>
+ AbstractMetaBuilderPrivate::createMetaEnum(const EnumModelItem &enumItem,
+ const QString &qualifiedName,
+ const TypeEntryPtr &typeEntry,
+ const AbstractMetaClassPtr &enclosing)
+{
+ const QString enumName = enumItem->name();
+ const QString className = enclosing ? enclosing->typeEntry()->qualifiedCppName() : QString{};
QString rejectReason;
if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) {
@@ -922,10 +944,6 @@ std::optional<AbstractMetaEnum>
metaEnum.setDeprecated(enumItem->isDeprecated());
metaEnum.setUnderlyingType(enumItem->underlyingType());
metaEnum.setSigned(enumItem->isSigned());
- if (enumsDeclarations.contains(qualifiedName)
- || enumsDeclarations.contains(enumName)) {
- metaEnum.setHasQEnumsDeclaration(true);
- }
auto enumTypeEntry = std::static_pointer_cast<EnumTypeEntry>(typeEntry);
metaEnum.setTypeEntry(enumTypeEntry);
@@ -972,6 +990,49 @@ std::optional<AbstractMetaEnum>
return metaEnum;
}
+// Add typedef'ed enumerations ("Using MyEnum=SomeNamespace::MyEnum") for which
+// a type entry exists.
+std::optional<AbstractMetaEnum>
+ AbstractMetaBuilderPrivate::traverseTypedefedEnum(const FileModelItem &dom,
+ const TypeDefModelItem &typeDefItem,
+ const AbstractMetaClassPtr &enclosing)
+{
+ if (enclosing && typeDefItem->accessPolicy() != Access::Public)
+ return std::nullopt; // Only for global/public enums typedef'ed into classes/namespaces
+ auto modelItem = CodeModel::findItem(typeDefItem->type().qualifiedName(), dom);
+ if (!modelItem || modelItem->kind() != _CodeModelItem::Kind_Enum)
+ return std::nullopt;
+ auto enumItem = std::static_pointer_cast<_EnumModelItem>(modelItem);
+ if (enumItem->accessPolicy() != Access::Public)
+ return std::nullopt;
+ // Name in class
+ QString qualifiedName = enclosing
+ ? enclosing->qualifiedCppName() + "::"_L1 + typeDefItem->name() : typeDefItem->name();
+ auto targetTypeEntry = TypeDatabase::instance()->findType(qualifiedName);
+ if (!targetTypeEntry || !targetTypeEntry->isEnum() || !targetTypeEntry->generateCode())
+ return std::nullopt;
+ auto targetEnumTypeEntry = std::static_pointer_cast<EnumTypeEntry>(targetTypeEntry);
+ auto sourceTypeEntry = TypeDatabase::instance()->findType(enumItem->qualifiedNameString());
+ if (!sourceTypeEntry || !sourceTypeEntry->isEnum())
+ return std::nullopt;
+
+ auto sourceEnumTypeEntry = std::static_pointer_cast<EnumTypeEntry>(sourceTypeEntry);
+ if (sourceEnumTypeEntry == targetEnumTypeEntry) // Reject "typedef Enum1 { V1 } Enum1;"
+ return std::nullopt;
+
+ const QString message = "Enum \""_L1 + qualifiedName + "\" is an alias to \""_L1
+ + enumItem->qualifiedNameString() + "\"."_L1;
+ ReportHandler::addGeneralMessage(message);
+ auto result = createMetaEnum(enumItem, qualifiedName, targetTypeEntry, enclosing);
+ if (result.has_value()) {
+ targetEnumTypeEntry->setAliasMode(EnumTypeEntry::AliasTarget);
+ targetEnumTypeEntry->setAliasTypeEntry(sourceEnumTypeEntry);
+ sourceEnumTypeEntry->setAliasMode(EnumTypeEntry::AliasSource);
+ sourceEnumTypeEntry->setAliasTypeEntry(targetEnumTypeEntry);
+ }
+ return result;
+}
+
AbstractMetaClassPtr
AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &dom,
const TypeDefModelItem &typeDef,
@@ -1177,7 +1238,7 @@ AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseClass(const FileModelIt
parseQ_Properties(metaClass, classItem->propertyDeclarations());
- traverseEnums(classItem, metaClass, classItem->enumsDeclarations());
+ traverseEnums(classItem, metaClass);
// Inner classes
{
@@ -1197,10 +1258,20 @@ AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseClass(const FileModelIt
// specific typedefs to be used as classes.
const TypeDefList typeDefs = classItem->typeDefs();
for (const TypeDefModelItem &typeDef : typeDefs) {
- const auto cls = traverseTypeDef(dom, typeDef, metaClass);
- if (cls) {
- cls->setEnclosingClass(metaClass);
- addAbstractMetaClass(cls, typeDef.get());
+ if (typeDef->accessPolicy() != Access::Private) {
+ switch (typeDef->underlyingTypeCategory()) {
+ case TypeCategory::Enum: {
+ const auto metaEnum = traverseTypedefedEnum(dom, typeDef, metaClass);
+ if (metaEnum.has_value())
+ metaClass->addEnum(metaEnum.value());
+ }
+ break;
+ default:
+ if (const auto cls = traverseTypeDef(dom, typeDef, metaClass)) {
+ cls->setEnclosingClass(metaClass);
+ addAbstractMetaClass(cls, typeDef.get());
+ }
+ }
}
}
@@ -1648,13 +1719,11 @@ bool AbstractMetaBuilderPrivate::setupInheritance(const AbstractMetaClassPtr &me
}
void AbstractMetaBuilderPrivate::traverseEnums(const ScopeModelItem &scopeItem,
- const AbstractMetaClassPtr &metaClass,
- const QStringList &enumsDeclarations)
+ const AbstractMetaClassPtr &metaClass)
{
const EnumList &enums = scopeItem->enums();
- const QSet<QString> enumsDeclarationSet(enumsDeclarations.cbegin(), enumsDeclarations.cend());
for (const EnumModelItem &enumItem : enums) {
- auto metaEnum = traverseEnum(enumItem, metaClass, enumsDeclarationSet);
+ auto metaEnum = traverseEnum(enumItem, metaClass);
if (metaEnum.has_value()) {
metaClass->addEnum(metaEnum.value());
}
@@ -1713,10 +1782,7 @@ AbstractMetaFunctionPtr
const auto &args = addedFunc->arguments();
- qsizetype argCount = args.size();
- // Check "foo(void)"
- if (argCount == 1 && args.constFirst().typeInfo.isVoid())
- argCount = 0;
+ const qsizetype argCount = args.size();
for (qsizetype i = 0; i < argCount; ++i) {
const AddedFunction::Argument &arg = args.at(i);
auto type = translateType(arg.typeInfo, metaClass, {}, errorMessage);
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h
index 45dd21e02..0a09d578b 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h
@@ -94,10 +94,14 @@ public:
AbstractMetaClassPtr traverseNamespace(const FileModelItem &dom,
const NamespaceModelItem &item);
std::optional<AbstractMetaEnum> traverseEnum(const EnumModelItem &item,
- const AbstractMetaClassPtr &enclosing,
- const QSet<QString> &enumsDeclarations);
- void traverseEnums(const ScopeModelItem &item, const AbstractMetaClassPtr &parent,
- const QStringList &enumsDeclarations);
+ const AbstractMetaClassPtr &enclosing);
+ void traverseEnums(const ScopeModelItem &item, const AbstractMetaClassPtr &parent);
+ std::optional<AbstractMetaEnum>
+ createMetaEnum(const EnumModelItem &enumItem, const QString &qualifiedName,
+ const TypeEntryPtr &typeEntry, const AbstractMetaClassPtr &enclosing);
+ std::optional<AbstractMetaEnum>
+ traverseTypedefedEnum(const FileModelItem &dom, const TypeDefModelItem &typeDefItem,
+ const AbstractMetaClassPtr &enclosing);
AbstractMetaFunctionList classFunctionList(const ScopeModelItem &scopeItem,
AbstractMetaClass::Attributes *constructorAttributes,
const AbstractMetaClassPtr &currentClass);
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
index 486d3d39c..3f2714ffc 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
@@ -96,8 +96,7 @@ void AbstractMetaEnumValue::setDocumentation(const Documentation &doc)
class AbstractMetaEnumData : public QSharedData
{
public:
- AbstractMetaEnumData() : m_deprecated(false),
- m_hasQenumsDeclaration(false), m_signed(true)
+ AbstractMetaEnumData() : m_deprecated(false), m_signed(true)
{
}
@@ -113,7 +112,6 @@ public:
EnumKind m_enumKind = CEnum;
Access m_access = Access::Public;
uint m_deprecated : 1;
- uint m_hasQenumsDeclaration : 1;
uint m_signed : 1;
};
@@ -298,17 +296,6 @@ bool AbstractMetaEnum::isAnonymous() const
return d->m_enumKind == AnonymousEnum;
}
-bool AbstractMetaEnum::hasQEnumsDeclaration() const
-{
- return d->m_hasQenumsDeclaration;
-}
-
-void AbstractMetaEnum::setHasQEnumsDeclaration(bool on)
-{
- if (d->m_hasQenumsDeclaration != on)
- d->m_hasQenumsDeclaration = on;
-}
-
EnumTypeEntryCPtr AbstractMetaEnum::typeEntry() const
{
return d->m_typeEntry;
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.h b/sources/shiboken6/ApiExtractor/abstractmetaenum.h
index cfaa9b9bb..c7edb74f6 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaenum.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.h
@@ -96,10 +96,6 @@ public:
bool isAnonymous() const;
- // Has the enum been declared inside a Q_ENUMS() macro in its enclosing class?
- bool hasQEnumsDeclaration() const;
- void setHasQEnumsDeclaration(bool on);
-
EnumTypeEntryCPtr typeEntry() const;
void setTypeEntry(const EnumTypeEntryCPtr &entry);
diff --git a/sources/shiboken6/ApiExtractor/addedfunction.cpp b/sources/shiboken6/ApiExtractor/addedfunction.cpp
index ee8009cfe..649296066 100644
--- a/sources/shiboken6/ApiExtractor/addedfunction.cpp
+++ b/sources/shiboken6/ApiExtractor/addedfunction.cpp
@@ -165,10 +165,12 @@ AddedFunction::AddedFunctionPtr
}
const auto paramString = signature.mid(openParenPos + 1, closingParenPos - openParenPos - 1);
- const auto params = AddedFunctionParser::splitParameters(paramString, errorMessage);
+ auto params = AddedFunctionParser::splitParameters(paramString, errorMessage);
if (params.isEmpty() && !errorMessage->isEmpty())
return {};
- for (const auto &p : params) {
+ if (params.size() == 1 && params.constFirst().type == "void"_L1)
+ params.clear(); // "void foo(void)" -> ""void foo()"
+ for (const auto &p : std::as_const(params)) {
TypeInfo type = p.type == u"..."
? TypeInfo::varArgsType() : TypeParser::parse(p.type, errorMessage);
if (!errorMessage->isEmpty()) {
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp
index 33f3f1ae6..cc2924287 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp
@@ -524,6 +524,27 @@ void BuilderPrivate::addTemplateInstantiations(const CXType &type,
typeName->remove(pos.first, pos.second - pos.first);
}
+static TypeCategory typeCategoryFromClang(CXTypeKind k)
+{
+ switch (k) {
+ case CXType_Void:
+ return TypeCategory::Void;
+ case CXType_Enum:
+ return TypeCategory::Enum;
+ case CXType_Pointer:
+ case CXType_BlockPointer:
+ return TypeCategory::Pointer;
+ case CXType_FunctionNoProto:
+ case CXType_FunctionProto:
+ return TypeCategory::Function;
+ default:
+ break;
+ }
+ if (k >= CXType_FirstBuiltin && k <= CXType_LastBuiltin)
+ return TypeCategory::Builtin;
+ return TypeCategory::Other;
+}
+
TypeInfo BuilderPrivate::createTypeInfoUncached(const CXType &type,
bool *cacheable) const
{
@@ -533,6 +554,7 @@ TypeInfo BuilderPrivate::createTypeInfoUncached(const CXType &type,
if (argCount >= 0) {
TypeInfo result = createTypeInfoUncached(clang_getResultType(pointeeType),
cacheable);
+ result.setTypeCategory(TypeCategory::Pointer);
result.setFunctionPointer(true);
for (int a = 0; a < argCount; ++a)
result.addArgument(createTypeInfoUncached(clang_getArgType(pointeeType, unsigned(a)),
@@ -542,6 +564,7 @@ TypeInfo BuilderPrivate::createTypeInfoUncached(const CXType &type,
}
TypeInfo typeInfo;
+ typeInfo.setTypeCategory(typeCategoryFromClang(clang_getCanonicalType(type).kind));
CXType nestedType = type;
for (; isArrayType(nestedType.kind); nestedType = clang_getArrayElementType(nestedType)) {
@@ -623,6 +646,7 @@ void BuilderPrivate::addTypeDef(const CXCursor &cursor, const CXType &cxType)
setFileName(cursor, item.get());
item->setType(createTypeInfo(cxType));
item->setScope(m_scope);
+ item->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor)));
m_scopeStack.back()->addTypeDef(item);
}
diff --git a/sources/shiboken6/ApiExtractor/classdocumentation.cpp b/sources/shiboken6/ApiExtractor/classdocumentation.cpp
index 1e721b589..ccc7b29d2 100644
--- a/sources/shiboken6/ApiExtractor/classdocumentation.cpp
+++ b/sources/shiboken6/ApiExtractor/classdocumentation.cpp
@@ -88,7 +88,7 @@ enum class WebXmlCodeTag
static WebXmlCodeTag tag(QStringView name)
{
- if (name == u"class" || name == u"namespace")
+ if (name == "class"_L1 || name == "struct"_L1 || name == "namespace"_L1)
return WebXmlCodeTag::Class;
if (name == u"enum")
return WebXmlCodeTag::Enum;
diff --git a/sources/shiboken6/ApiExtractor/documentation.h b/sources/shiboken6/ApiExtractor/documentation.h
index 580d8f969..a623529ca 100644
--- a/sources/shiboken6/ApiExtractor/documentation.h
+++ b/sources/shiboken6/ApiExtractor/documentation.h
@@ -29,6 +29,7 @@ public:
bool equals(const Documentation &rhs) const;
+ bool hasDetailed() const { return !m_detailed.isEmpty(); }
const QString &detailed() const { return m_detailed; }
void setDetailed(const QString &detailed);
diff --git a/sources/shiboken6/ApiExtractor/enumtypeentry.h b/sources/shiboken6/ApiExtractor/enumtypeentry.h
index 3360d7db5..633ab3183 100644
--- a/sources/shiboken6/ApiExtractor/enumtypeentry.h
+++ b/sources/shiboken6/ApiExtractor/enumtypeentry.h
@@ -13,6 +13,12 @@ class EnumTypeEntryPrivate;
class EnumTypeEntry : public ConfigurableTypeEntry
{
public:
+ enum AliasMode : unsigned char {
+ NoAlias,
+ AliasSource, // Source of a C++ alias "using ThatEnum = ThisEnum";
+ AliasTarget // Target of a C++ alias "using ThisEnum = ThatEnum";
+ };
+
explicit EnumTypeEntry(const QString &entryName,
const QVersionNumber &vr,
const TypeEntryCPtr &parent);
@@ -40,6 +46,12 @@ public:
QString docFile() const;
void setDocFile(const QString &df);
+ AliasMode aliasMode() const;
+ void setAliasMode(AliasMode am);
+
+ EnumTypeEntryCPtr aliasTypeEntry() const;
+ void setAliasTypeEntry(const EnumTypeEntryCPtr &entry);
+
TypeEntry *clone() const override;
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp
index 5647cccc5..1abfe466b 100644
--- a/sources/shiboken6/ApiExtractor/messages.cpp
+++ b/sources/shiboken6/ApiExtractor/messages.cpp
@@ -171,7 +171,7 @@ static void msgFormatEnumType(Stream &str,
{
switch (enumItem->enumKind()) {
case CEnum:
- str << "Enum '" << enumItem->qualifiedName().join(u"::"_s) << '\'';
+ str << "Enum '" << enumItem->qualifiedNameString() << '\'';
break;
case AnonymousEnum: {
const EnumeratorList &values = enumItem->enumerators();
@@ -194,7 +194,7 @@ static void msgFormatEnumType(Stream &str,
}
break;
case EnumClass:
- str << "Scoped enum '" << enumItem->qualifiedName().join(u"::"_s) << '\'';
+ str << "Scoped enum '" << enumItem->qualifiedNameString() << '\'';
break;
}
if (!className.isEmpty())
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
index a5994bd75..8a56c9eee 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
@@ -160,6 +160,11 @@ QStringList _CodeModelItem::qualifiedName() const
return q;
}
+QString _CodeModelItem::qualifiedNameString() const
+{
+ return qualifiedName().join("::"_L1);
+}
+
QString _CodeModelItem::name() const
{
return m_name;
@@ -453,11 +458,6 @@ FunctionModelItem _ScopeModelItem::declaredFunction(const FunctionModelItem &ite
_ScopeModelItem::~_ScopeModelItem() = default;
-void _ScopeModelItem::addEnumsDeclaration(const QString &enumsDeclaration)
-{
- m_enumsDeclarations << enumsDeclaration;
-}
-
void _ScopeModelItem::addClass(const ClassModelItem &item)
{
m_classes.append(item);
@@ -520,15 +520,13 @@ void _ScopeModelItem::appendScope(const _ScopeModelItem &other)
m_templateTypeAliases += other.m_templateTypeAliases;
m_variables += other.m_variables;
m_functions += other.m_functions;
- m_enumsDeclarations += other.m_enumsDeclarations;
}
bool _ScopeModelItem::isEmpty() const
{
return m_classes.isEmpty() && m_enums.isEmpty()
&& m_typeDefs.isEmpty() && m_templateTypeAliases.isEmpty()
- && m_variables.isEmpty() && m_functions.isEmpty()
- && m_enumsDeclarations.isEmpty();
+ && m_variables.isEmpty() && m_functions.isEmpty();
}
/* This function removes MSVC export declarations of non-type template
@@ -1208,11 +1206,26 @@ void _TypeDefModelItem::setType(const TypeInfo &type)
m_type = type;
}
+TypeCategory _TypeDefModelItem::underlyingTypeCategory() const
+{
+ return m_type.typeCategory();
+}
+
+Access _TypeDefModelItem::accessPolicy() const
+{
+ return m_accessPolicy;
+}
+
+void _TypeDefModelItem::setAccessPolicy(Access accessPolicy)
+{
+ m_accessPolicy = accessPolicy;
+}
+
#ifndef QT_NO_DEBUG_STREAM
void _TypeDefModelItem::formatDebug(QDebug &d) const
{
_CodeModelItem::formatDebug(d);
- d << ", type=" << m_type;
+ d << ", " << m_accessPolicy << ", type=" << m_type;
}
#endif // !QT_NO_DEBUG_STREAM
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.h b/sources/shiboken6/ApiExtractor/parser/codemodel.h
index fb46fab82..77082efa5 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel.h
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel.h
@@ -120,6 +120,7 @@ public:
int kind() const;
QStringList qualifiedName() const;
+ QString qualifiedNameString() const;
QString name() const;
void setName(const QString &name);
@@ -211,9 +212,6 @@ public:
TemplateTypeAliasModelItem findTemplateTypeAlias(QAnyStringView name) const;
VariableModelItem findVariable(QAnyStringView name) const;
- void addEnumsDeclaration(const QString &enumsDeclaration);
- QStringList enumsDeclarations() const { return m_enumsDeclarations; }
-
FunctionModelItem declaredFunction(const FunctionModelItem &item);
bool isEmpty() const;
@@ -250,9 +248,6 @@ private:
TemplateTypeAliasList m_templateTypeAliases;
VariableList m_variables;
FunctionList m_functions;
-
-private:
- QStringList m_enumsDeclarations;
};
class _ClassModelItem: public _ScopeModelItem
@@ -564,11 +559,17 @@ public:
TypeInfo type() const;
void setType(const TypeInfo &type);
+ TypeCategory underlyingTypeCategory() const;
+
+ Access accessPolicy() const;
+ void setAccessPolicy(Access accessPolicy);
+
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
#endif
private:
+ Access m_accessPolicy = Access::Public;
TypeInfo m_type;
};
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h
index e5c429bd0..c3bb10e5f 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel_enums.h
@@ -58,4 +58,14 @@ enum class FunctionAttribute {
Q_DECLARE_FLAGS(FunctionAttributes, FunctionAttribute)
Q_DECLARE_OPERATORS_FOR_FLAGS(FunctionAttributes)
+// C++ type category for TypeInfo, reflecting clang's CXTypeKind
+enum class TypeCategory : unsigned char {
+ Other,
+ Builtin,
+ Enum,
+ Pointer,
+ Function,
+ Void
+};
+
#endif // CODEMODEL_ENUMS_H
diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp
index 93627e6d5..c530cafea 100644
--- a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp
+++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp
@@ -25,7 +25,6 @@ class TypeInfoData : public QSharedData
public:
TypeInfoData();
- bool isVoid() const;
bool equals(const TypeInfoData &other) const;
bool isStdType() const;
void simplifyStdType();
@@ -48,6 +47,7 @@ public:
};
ReferenceType m_referenceType = NoReference;
+ TypeCategory m_category = TypeCategory::Other;
};
TypeInfoData::TypeInfoData() : flags(0)
@@ -143,18 +143,21 @@ void TypeInfo::addName(const QString &n)
d->m_qualifiedName.append(n);
}
-bool TypeInfoData::isVoid() const
+bool TypeInfo::isVoid() const
{
- return m_indirections.isEmpty() && m_referenceType == NoReference
- && m_arguments.isEmpty() && m_arrayElements.isEmpty()
- && m_instantiations.isEmpty()
- && m_qualifiedName.size() == 1
- && m_qualifiedName.constFirst() == u"void";
+ return d->m_category == TypeCategory::Void;
}
-bool TypeInfo::isVoid() const
+TypeCategory TypeInfo::typeCategory() const
+{
+ return d->m_category;
+
+}
+
+void TypeInfo::setTypeCategory(TypeCategory c)
{
- return d->isVoid();
+ if (d->m_category != c)
+ d->m_category = c;
}
bool TypeInfo::isConstant() const
@@ -457,6 +460,7 @@ bool TypeInfoData::equals(const TypeInfoData &other) const
return flags == other.flags
&& m_qualifiedName == other.m_qualifiedName
+ && m_category == other.m_category
&& (!m_functionPointer || m_arguments == other.m_arguments)
&& m_instantiations == other.m_instantiations;
}
@@ -584,6 +588,23 @@ void TypeInfo::formatDebug(QDebug &debug) const
debug << ", [const]";
if (d->m_volatile)
debug << ", [volatile]";
+ switch (d->m_category) {
+ case TypeCategory::Other:
+ case TypeCategory::Void:
+ break;
+ case TypeCategory::Builtin:
+ debug << ", [builtin]";
+ break;
+ case TypeCategory::Enum:
+ debug << ", [enum]";
+ break;
+ case TypeCategory::Pointer:
+ debug << ", [pointer]";
+ break;
+ case TypeCategory::Function:
+ debug << ", [function";
+ break;
+ }
if (!d->m_indirections.isEmpty()) {
debug << ", indirections=";
for (auto i : d->m_indirections)
diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.h b/sources/shiboken6/ApiExtractor/parser/typeinfo.h
index 6f75b5737..092fbb724 100644
--- a/sources/shiboken6/ApiExtractor/parser/typeinfo.h
+++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.h
@@ -48,6 +48,9 @@ public:
bool isVoid() const;
+ TypeCategory typeCategory() const;
+ void setTypeCategory(TypeCategory c);
+
bool isConstant() const;
void setConstant(bool is);
diff --git a/sources/shiboken6/ApiExtractor/qtdocparser.cpp b/sources/shiboken6/ApiExtractor/qtdocparser.cpp
index c7361b87a..a9b76d32c 100644
--- a/sources/shiboken6/ApiExtractor/qtdocparser.cpp
+++ b/sources/shiboken6/ApiExtractor/qtdocparser.cpp
@@ -30,6 +30,7 @@
#include <algorithm>
#include <iterator>
+#include <utility>
using namespace Qt::StringLiterals;
@@ -245,23 +246,35 @@ QtDocParser::FunctionDocumentationOpt
return std::nullopt;
}
-// Extract the <brief> section from a WebXML (class) documentation and remove it
-// from the source.
-static QString extractBrief(QString *value)
+// Extract the <brief>/detailed sections from a WebXML (class) documentation (from <description>)
+static std::pair<QString, QString> extractBrief(QString value)
{
- const auto briefStart = value->indexOf(briefStartElement);
- if (briefStart < 0)
- return {};
- const auto briefEnd = value->indexOf(briefEndElement,
- briefStart + briefStartElement.size());
- if (briefEnd < briefStart)
- return {};
- const auto briefLength = briefEnd + briefEndElement.size() - briefStart;
- QString briefValue = value->mid(briefStart, briefLength);
- briefValue.insert(briefValue.size() - briefEndElement.size(),
- u"<rst> More_...</rst>"_s);
- value->remove(briefStart, briefLength);
- return briefValue;
+ std::pair<QString, QString> result;
+ const auto briefStart = value.indexOf(briefStartElement);
+ if (briefStart > 0) {
+ const auto briefEnd = value.indexOf(briefEndElement,
+ briefStart + briefStartElement.size());
+ if (briefEnd > briefStart) {
+ const auto briefLength = briefEnd + briefEndElement.size() - briefStart;
+ if (briefLength > briefStartElement.size() + briefEndElement.size())
+ result.first = value.sliced(briefStart, briefLength);
+ value.remove(briefStart, briefLength);
+ // Remove any space/newlines between the <brief/> element and its
+ // surrounding XML elements.
+ auto lastElement = value.lastIndexOf(u'>', briefStart);
+ if (lastElement != -1) {
+ ++lastElement;
+ const auto nextElement = value.indexOf(u'<', briefStart);
+ if (nextElement > lastElement)
+ value.remove(lastElement, nextElement - lastElement);
+ }
+ }
+ }
+
+ if (value != "<description></description>"_L1)
+ result.second = value;
+
+ return result;
}
// Apply the documentation parsed from WebXML to a AbstractMetaFunction and complete argument
@@ -408,13 +421,12 @@ QString QtDocParser::fillDocumentation(const AbstractMetaClassPtr &metaClass)
qCWarning(lcShibokenDoc, "%s",
qPrintable(msgCannotFindDocumentation(sourceFileName, "class", className, {})));
}
- const QString brief = extractBrief(&docString);
+ const auto descriptionPair = extractBrief(docString);
Documentation doc;
doc.setSourceFile(sourceFileName);
- if (!brief.isEmpty())
- doc.setValue(brief, DocumentationType::Brief);
- doc.setValue(docString);
+ doc.setValue(descriptionPair.first, DocumentationType::Brief);
+ doc.setValue(descriptionPair.second, DocumentationType::Detailed);
metaClass->setDocumentation(doc);
//Functions Documentation
diff --git a/sources/shiboken6/ApiExtractor/tests/a.xml b/sources/shiboken6/ApiExtractor/tests/a.xml
index 3c09d3800..bb771ed1f 100644
--- a/sources/shiboken6/ApiExtractor/tests/a.xml
+++ b/sources/shiboken6/ApiExtractor/tests/a.xml
@@ -3,7 +3,7 @@
<WebXML>
<document>
<class name="A">
- <description>oi
+ <description><para>before brief</para>
<brief>Brief description</brief>
<para>Paragraph number 1</para>
<para>Paragraph number 2</para>
diff --git a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp
index c2fc3b212..9e59ebde6 100644
--- a/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp
+++ b/sources/shiboken6/ApiExtractor/tests/testmodifydocumentation.cpp
@@ -28,7 +28,7 @@ R"(<typesystem package="Foo">
</value-type>
<value-type name='A'>
<modify-documentation xpath='description/brief'>&lt;brief>Modified Brief&lt;/brief></modify-documentation>
- <modify-documentation xpath='description/para[3]'>&lt;para>Some changed contents here&lt;/para></modify-documentation>
+ <modify-documentation xpath='description/para[4]'>&lt;para>Some changed contents here&lt;/para></modify-documentation>
</value-type>
</typesystem>
)";
@@ -66,8 +66,7 @@ R"(<typesystem package="Foo">
const char expectedDoc[] =
R"(<?xml version="1.0"?>
-<description>oi
-<para>Paragraph number 1</para>
+<description><para>before brief</para><para>Paragraph number 1</para>
<para>Paragraph number 2</para>
<para>Some changed contents here</para>
</description>
diff --git a/sources/shiboken6/ApiExtractor/typesystem.cpp b/sources/shiboken6/ApiExtractor/typesystem.cpp
index 46e88291d..c02ec0c93 100644
--- a/sources/shiboken6/ApiExtractor/typesystem.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystem.cpp
@@ -1225,7 +1225,9 @@ public:
FlagsTypeEntryPtr m_flags;
QString m_cppType;
QString m_docFile;
+ std::weak_ptr<const EnumTypeEntry> m_aliasTypeEntry;
TypeSystem::PythonEnumType m_pythonEnumType = TypeSystem::PythonEnumType::Unspecified;
+ EnumTypeEntry::AliasMode m_aliasMode = EnumTypeEntry::AliasMode::NoAlias;
};
EnumTypeEntry::EnumTypeEntry(const QString &entryName,
@@ -1330,6 +1332,30 @@ void EnumTypeEntry::setDocFile(const QString &df)
d->m_docFile = df;
}
+EnumTypeEntry::AliasMode EnumTypeEntry::aliasMode() const
+{
+ S_D(const EnumTypeEntry);
+ return d->m_aliasMode;
+}
+
+void EnumTypeEntry::setAliasMode(AliasMode am)
+{
+ S_D(EnumTypeEntry);
+ d->m_aliasMode = am;
+}
+
+EnumTypeEntryCPtr EnumTypeEntry::aliasTypeEntry() const
+{
+ S_D(const EnumTypeEntry);
+ return d->m_aliasTypeEntry.lock();
+}
+
+void EnumTypeEntry::setAliasTypeEntry(const EnumTypeEntryCPtr &entry)
+{
+ S_D(EnumTypeEntry);
+ d->m_aliasTypeEntry = entry;
+}
+
TypeEntry *EnumTypeEntry::clone() const
{
S_D(const EnumTypeEntry);
diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst
index 798ef5719..7fe4df392 100644
--- a/sources/shiboken6/doc/typesystem_specifying_types.rst
+++ b/sources/shiboken6/doc/typesystem_specifying_types.rst
@@ -347,6 +347,23 @@ production of ABI compatible bindings.
The **flags-revision** attribute has the same purposes of **revision** attribute but
is used for the QFlag related to this enum.
+An enum can also be a C++ type alias:
+
+.. code-block:: c++
+
+ enum Option { Value1 = 0; }
+
+ class SomeClass {
+ public:
+ using OptionAlias = Option;
+ };
+
+In this case, when specifying `<enum-type name="OptionAlias"...>` in
+`SomeClass`, an enumeration `OptionAlias` will be generated into the class. The
+values of `OptionAlias` and `Option` can be used interchangeably. This feature
+is specifically intended for renaming enumerations by deprecating; it works for
+at most one alias.
+
.. _reject-enum-value:
reject-enum-value
diff --git a/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp
index c99acb3d2..87e01f35b 100644
--- a/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp
+++ b/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp
@@ -507,6 +507,25 @@ void QtDocGenerator::writeDetailedDescription(TextStream &s,
parsedImages);
}
+enum ClassDescriptionMode
+{
+ NoDescription,
+ BriefOnly,
+ DetailedOnly,
+ BriefAndDetailed,
+ BriefAndDetailedSections,
+};
+
+static ClassDescriptionMode classDescriptionMode(const Documentation &doc)
+{
+ if (!doc.hasDetailed())
+ return doc.hasBrief() ? BriefOnly : NoDescription;
+ if (!doc.hasBrief())
+ return DetailedOnly;
+ return doc.detailed().contains("<section"_L1)
+ ? BriefAndDetailedSections : BriefAndDetailed;
+}
+
void QtDocGenerator::doGenerateClass(TextStream &s, const QString &targetDir,
const AbstractMetaClassCPtr &metaClass)
{
@@ -521,8 +540,33 @@ void QtDocGenerator::doGenerateClass(TextStream &s, const QString &targetDir,
QtXmlToSphinxImages parsedImages;
auto documentation = metaClass->documentation();
const QString scope = classScope(metaClass);
- if (documentation.hasBrief())
+
+ const auto descriptionMode = classDescriptionMode(documentation);
+ switch (descriptionMode) {
+ case NoDescription:
+ case DetailedOnly:
+ break;
+ case BriefOnly:
writeFormattedBriefText(s, documentation, scope, &parsedImages);
+ break;
+ case BriefAndDetailed: {
+ // A "collapse" sphinx directive can be used for brief/expanding to details
+ // for descriptions consisting of a paragraph sequence.
+ writeFormattedBriefText(s, documentation, scope, &parsedImages);
+ s << "\n\n.. collapse:: Details\n\n";
+ Indentation detailIndent(s);
+ writeDetailedDescription(s, metaClass, scope, &parsedImages);
+ }
+ break;
+ case BriefAndDetailedSections: {
+ // If the the description has nested <section>'s (which break collapse::), we
+ // use a 'more' label for the detailed text to be written further down.
+ QString brief = documentation.brief();
+ brief.insert(brief.lastIndexOf(u'<'), "<rst> More_...</rst>"_L1);
+ writeFormattedText(s, brief, documentation.format(), scope, &parsedImages);
+ }
+ break;
+ }
if (!metaClass->baseClasses().isEmpty()) {
if (m_options.inheritanceDiagram) {
@@ -560,9 +604,17 @@ void QtDocGenerator::doGenerateClass(TextStream &s, const QString &targetDir,
" translation, you can also let us know by creating a ticket on\n"
" https:/bugreports.qt.io/projects/PYSIDE\n\n";
- s << '\n' << headline("Detailed Description") << ".. _More:\n";
-
- writeDetailedDescription(s, metaClass, scope, &parsedImages);
+ switch (descriptionMode) {
+ case DetailedOnly:
+ case BriefAndDetailedSections:
+ s << '\n' << headline("Detailed Description");
+ if (descriptionMode == BriefAndDetailedSections)
+ s << ".. _More:\n";
+ writeDetailedDescription(s, metaClass, scope, &parsedImages);
+ break;
+ default:
+ break;
+ }
writeEnums(s, metaClass->enums(), scope, &parsedImages);
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 65b03e206..c90a0557c 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -1737,6 +1737,17 @@ void CppGenerator::writeEnumConverterFunctions(TextStream &s, const AbstractMeta
writePythonToCppFunction(s, c.toString(), enumConverterPythonType, typeName);
QString pyTypeCheck = u"PyObject_TypeCheck(pyIn, "_s + enumPythonType + u')';
+ switch (metaEnum.typeEntry()->aliasMode()) {
+ case EnumTypeEntry::NoAlias:
+ break;
+ case EnumTypeEntry::AliasSource:
+ case EnumTypeEntry::AliasTarget: {
+ const QString &aliasSourceType = cpythonTypeNameExt(metaEnum.typeEntry()->aliasTypeEntry());
+ pyTypeCheck += "\n || PyObject_TypeCheck(pyIn, "_L1 + aliasSourceType + u')';
+ }
+ break;
+ }
+
writeIsPythonConvertibleToCppFunction(s, enumConverterPythonType, typeName, pyTypeCheck);
c.clear();
@@ -3538,9 +3549,16 @@ void CppGenerator::writeIsPythonConvertibleToCppFunction(TextStream &s,
if (!condition.contains(u"pyIn"))
s << sbkUnusedVariableCast("pyIn");
}
- s << "if (" << condition << ")\n" << indent
- << "return " << pythonToCppFuncName << ";\n" << outdent
- << "return {};\n" << outdent << "}\n";
+
+ const bool useBrace = condition.contains(u'\n');
+ s << "if (" << condition << ')';
+ if (useBrace)
+ s<< " {";
+ s << '\n' << indent
+ << "return " << pythonToCppFuncName << ";\n" << outdent;
+ if (useBrace)
+ s<< "}\n";
+ s << "return {};\n" << outdent << "}\n";
}
void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
@@ -6022,8 +6040,8 @@ void CppGenerator::writeStaticFieldInitialization(TextStream &s,
if (parts.size() < 4) {
s << "\nPyTypeObject *" << getSimpleClassStaticFieldsInitFunctionName(metaClass)
<< "(PyObject *module)\n{\n" << indent
- << "auto *obType = PyObject_GetAttrString(module, \"" << metaClass->name() << "\");\n"
- << "auto *type = reinterpret_cast<PyTypeObject *>(obType);\n"
+ << "Shiboken::AutoDecRef obType(PyObject_GetAttrString(module, \"" << metaClass->name() << "\"));\n"
+ << "auto *type = reinterpret_cast<PyTypeObject *>(obType.object());\n"
<< "Shiboken::AutoDecRef dict(PepType_GetDict(type));\n";
} else {
s << "\nPyTypeObject *" << getSimpleClassStaticFieldsInitFunctionName(metaClass)
@@ -6822,7 +6840,8 @@ void CppGenerator::writeContainerConverterInitFunc(TextStream &s,
void CppGenerator::writeOpaqueContainerConverterRegisterFunc(TextStream &s, const QString &funcName,
const OpaqueContainerTypeHash &opaqueContainers)
{
- s << "static void " << funcName << "(PyObject *module)\n{\n" << indent;
+ s << "static void " << funcName << "(PyObject *module)\n{\n" << indent
+ << "PyTypeObject *pyType{};\n";
if (usePySideExtensions()) {
const bool hasQVariantConversion =
std::any_of(opaqueContainers.cbegin(), opaqueContainers.cend(),
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
index 591d86f10..826ad89af 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
@@ -285,8 +285,9 @@ CppGenerator::OpaqueContainerData
result.pythonToConverterFunctionName);
TextStream registrationStr(&result.registrationCode, TextStream::Language::Cpp);
- registrationStr << "Py_XINCREF(" << typeFName << "());\nPepModule_AddType(module, "
- << typeFName << "());\n";
+ registrationStr << "pyType = " << typeFName << "();\n"
+ << "Py_XINCREF(reinterpret_cast<PyObject *>(pyType));\n"
+ << "PepModule_AddType(module, pyType);\n";
if (!result.hasQVariantConversion)
return result;
diff --git a/sources/shiboken6/generator/shiboken/headergenerator.cpp b/sources/shiboken6/generator/shiboken/headergenerator.cpp
index 181f04a9d..6ffeef9a3 100644
--- a/sources/shiboken6/generator/shiboken/headergenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/headergenerator.cpp
@@ -814,7 +814,7 @@ bool HeaderGenerator::finishGeneration()
TextStream privateTypeFunctions(&privateParameters.typeFunctions, TextStream::Language::Cpp);
for (const AbstractMetaEnum &cppEnum : api().globalEnums()) {
- if (!cppEnum.isAnonymous()) {
+ if (!cppEnum.isAnonymous() && cppEnum.typeEntry()->aliasMode() != EnumTypeEntry::AliasSource) {
const auto te = cppEnum.typeEntry();
if (te->hasConfigCondition())
parameters.conditionalIncludes[te->configCondition()].append(te->include());
@@ -846,8 +846,10 @@ bool HeaderGenerator::finishGeneration()
ConfigurableScope configScope(typeFunctionsStr, classType);
for (const AbstractMetaEnum &cppEnum : metaClass->enums()) {
- if (cppEnum.isAnonymous() || cppEnum.isPrivate())
+ if (cppEnum.isAnonymous() || cppEnum.isPrivate()
+ || cppEnum.typeEntry()->aliasMode() == EnumTypeEntry::AliasSource) {
continue;
+ }
if (const auto inc = cppEnum.typeEntry()->include(); inc != classInclude)
par.includes.insert(inc);
writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum);
diff --git a/sources/shiboken6/libshiboken/sbkbindingutils.cpp b/sources/shiboken6/libshiboken/sbkbindingutils.cpp
index efa25c547..d61551b3b 100644
--- a/sources/shiboken6/libshiboken/sbkbindingutils.cpp
+++ b/sources/shiboken6/libshiboken/sbkbindingutils.cpp
@@ -5,6 +5,7 @@
#include "autodecref.h"
#include "sbkstring.h"
+#include "sbkpep.h"
#include "sbkstaticstrings_p.h"
#include <algorithm>
diff --git a/sources/shiboken6/libshiboken/sbkmodule.cpp b/sources/shiboken6/libshiboken/sbkmodule.cpp
index 20566ec50..c8db111ff 100644
--- a/sources/shiboken6/libshiboken/sbkmodule.cpp
+++ b/sources/shiboken6/libshiboken/sbkmodule.cpp
@@ -140,7 +140,7 @@ static PyTypeObject *incarnateType(PyObject *module, const char *name,
initSelectableFeature(saveFeature);
// - assign this object to the name in the module
- Py_INCREF(type);
+ Py_INCREF(reinterpret_cast<PyObject *>(type));
PepModule_AddType(module, type); // steals reference
// - remove the entry, if not by something cleared.
if (!nameToFunc.empty())
diff --git a/sources/shiboken6/tests/libsample/functions.h b/sources/shiboken6/tests/libsample/functions.h
index b745aed6b..ef88e543e 100644
--- a/sources/shiboken6/tests/libsample/functions.h
+++ b/sources/shiboken6/tests/libsample/functions.h
@@ -21,6 +21,8 @@ enum GlobalEnum {
ThirdThing
};
+using GlobalEnumAlias = GlobalEnum;
+
enum GlobalOverloadFuncEnum {
GlobalOverloadFunc_i,
GlobalOverloadFunc_d
diff --git a/sources/shiboken6/tests/libsample/samplenamespace.cpp b/sources/shiboken6/tests/libsample/samplenamespace.cpp
index 3836f43aa..5e7b67a62 100644
--- a/sources/shiboken6/tests/libsample/samplenamespace.cpp
+++ b/sources/shiboken6/tests/libsample/samplenamespace.cpp
@@ -11,6 +11,16 @@
namespace SampleNamespace
{
+SomeClass::OptionAlias SomeClass::passThroughOptionAlias(OptionAlias ov)
+{
+ return ov;
+}
+
+Option SomeClass::passThroughOption(Option ov)
+{
+ return ov;
+}
+
// PYSIDE-817, scoped enums must not be converted to int in the wrappers generated
// for the protected hacks
SomeClass::PublicScopedEnum SomeClass::protectedMethodReturningPublicScopedEnum() const
diff --git a/sources/shiboken6/tests/libsample/samplenamespace.h b/sources/shiboken6/tests/libsample/samplenamespace.h
index 63dc2f316..1613ce630 100644
--- a/sources/shiboken6/tests/libsample/samplenamespace.h
+++ b/sources/shiboken6/tests/libsample/samplenamespace.h
@@ -5,6 +5,7 @@
#define SAMPLENAMESPACE_H
#include "libsamplemacros.h"
+#include "samplenamespace.h"
#include "str.h"
#include "point.h"
#include "objecttype.h"
@@ -86,6 +87,12 @@ class LIBSAMPLE_API SomeClass
public:
enum class PublicScopedEnum { v1, v2 };
+ // Alias an enumeration
+ using OptionAlias = Option;
+ inline static constexpr auto None_ = Option::None_;
+ inline static constexpr auto RandomNumber = Option::RandomNumber;
+ inline static constexpr auto UnixTime = Option::UnixTime;
+
class SomeInnerClass
{
public:
@@ -107,16 +114,21 @@ public:
inline int someMethod(SomeInnerClass *) { return 0; }
virtual OkThisIsRecursiveEnough *someVirtualMethod(OkThisIsRecursiveEnough *arg)
{ return arg; }
- };
+ }; // OkThisIsRecursiveEnough
protected:
enum ProtectedEnum {
ProtectedItem0,
ProtectedItem1
};
- };
+ }; // SomeInnerClass
+
struct SomeOtherInnerClass {
std::list<SomeInnerClass> someInnerClasses;
};
+
+ static OptionAlias passThroughOptionAlias(OptionAlias ov);
+ static Option passThroughOption(Option ov);
+
protected:
enum ProtectedEnum {
ProtectedItem0,
diff --git a/sources/shiboken6/tests/samplebinding/namespace_test.py b/sources/shiboken6/tests/samplebinding/namespace_test.py
index 0d67c7497..0e92d6e27 100644
--- a/sources/shiboken6/tests/samplebinding/namespace_test.py
+++ b/sources/shiboken6/tests/samplebinding/namespace_test.py
@@ -64,6 +64,20 @@ class TestClassesUnderNamespace(unittest.TestCase):
cls.setValue(SampleNamespace.EnumWithinInlineNamespace.EWIN_Value1)
self.assertEqual(cls.value(), SampleNamespace.EnumWithinInlineNamespace.EWIN_Value1)
+ def testEnumAlias(self):
+ """Test whether an enumeration can be aliased to another one and values
+ can be used interchangeably."""
+ expected = SampleNamespace.SomeClass.OptionAlias.None_
+ actual = SampleNamespace.SomeClass.passThroughOptionAlias(expected)
+ self.assertEqual(expected, actual)
+ actual = SampleNamespace.SomeClass.passThroughOption(expected)
+ self.assertEqual(expected, actual)
+ # The alias source values should also work
+ actual = SampleNamespace.SomeClass.passThroughOptionAlias(SampleNamespace.Option.None_)
+ self.assertEqual(expected, actual)
+ actual = SampleNamespace.SomeClass.passThroughOption(SampleNamespace.Option.None_)
+ self.assertEqual(expected, actual)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
index 5503d9bb7..711db9c4a 100644
--- a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
+++ b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
@@ -420,6 +420,7 @@
-->
<enum-type name="GlobalEnum"/>
<enum-type name="GlobalOverloadFuncEnum"/>
+ <enum-type name="GlobalEnumAlias"/>
<enum-type identified-by-value="AnonymousGlobalEnum_Value0"/>
@@ -437,6 +438,10 @@
<enum-type name="SampleNamespace"/>
</object-type>
<value-type name="SomeClass">
+ <enum-type name="OptionAlias"/>
+ <modify-field name="None_" remove="true"/>
+ <modify-field name="RandomNumber" remove="true"/>
+ <modify-field name="RandomNumber" remove="true"/>
<enum-type name="PublicScopedEnum"/>
<value-type name="SomeInnerClass">
<object-type name="OkThisIsRecursiveEnough">