Skip to content

Commit e37128c

Browse files
usiemsjcfr
authored andcommitted
[Backport generator] Handle enum classes
Since the enum values can be duplicates (they only need to be unique in the scope of the enum class) I opted to prefix them with the enum class name (and an underscore) in the generated wrapper. It would have been nice to use a Python Enum class instead, but after a quick look this seemed to be quite a lot of work. (cherry picked from commit MeVisLab/pythonqt@c707bcc)
1 parent a732a02 commit e37128c

File tree

7 files changed

+32
-1
lines changed

7 files changed

+32
-1
lines changed

generator/abstractmetabuilder.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,8 @@ AbstractMetaEnum *AbstractMetaBuilder::traverseEnum(EnumModelItem enum_item, Abs
10081008
return 0;
10091009
}
10101010

1011+
static_cast<EnumTypeEntry*>(type_entry)->setEnumClass(enum_item->isEnumClass());
1012+
10111013
AbstractMetaEnum *meta_enum = createMetaEnum();
10121014
if ( enumsDeclarations.contains(qualified_name)
10131015
|| enumsDeclarations.contains(enum_name)) {

generator/parser/ast.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ struct EnumSpecifierAST: public TypeSpecifierAST
421421

422422
NameAST *name{};
423423
const ListNode<EnumeratorAST*> *enumerators{};
424+
bool is_enum_class{};
424425
};
425426

426427
struct EnumeratorAST: public AST

generator/parser/binder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,7 @@ void Binder::visitEnumSpecifier(EnumSpecifierAST *node)
796796

797797
_M_current_enum = model()->create<EnumModelItem>();
798798
_M_current_enum->setAccessPolicy(_M_current_access);
799+
_M_current_enum->setEnumClass(node->is_enum_class);
799800
updateItemPosition (_M_current_enum->toItem(), node);
800801
_M_current_enum->setName(name);
801802
_M_current_enum->setScope(enumScope->qualifiedName());

generator/parser/codemodel.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,9 @@ class _EnumModelItem: public _CodeModelItem
676676
CodeModel::AccessPolicy accessPolicy() const;
677677
void setAccessPolicy(CodeModel::AccessPolicy accessPolicy);
678678

679+
bool isEnumClass() const { return _M_isEnumClass; }
680+
void setEnumClass(bool isEnumClass) { _M_isEnumClass = isEnumClass; }
681+
679682
EnumeratorList enumerators() const;
680683
void addEnumerator(EnumeratorModelItem item);
681684
void removeEnumerator(EnumeratorModelItem item);
@@ -689,6 +692,7 @@ class _EnumModelItem: public _CodeModelItem
689692
private:
690693
CodeModel::AccessPolicy _M_accessPolicy;
691694
EnumeratorList _M_enumerators;
695+
bool _M_isEnumClass{};
692696

693697
private:
694698
_EnumModelItem(const _EnumModelItem &other);

generator/parser/parser.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,8 +1548,10 @@ bool Parser::parseEnumSpecifier(TypeSpecifierAST *&node)
15481548

15491549
CHECK(Token_enum);
15501550

1551+
bool enum_class{};
15511552
if (token_stream.lookAhead() == Token_class)
15521553
{
1554+
enum_class = true;
15531555
nextToken();
15541556
}
15551557

@@ -1576,6 +1578,7 @@ bool Parser::parseEnumSpecifier(TypeSpecifierAST *&node)
15761578

15771579
EnumSpecifierAST *ast = CreateNode<EnumSpecifierAST>(_M_pool);
15781580
ast->name = name;
1581+
ast->is_enum_class = enum_class;
15791582

15801583
EnumeratorAST *enumerator = 0;
15811584
if (parseEnumerator(enumerator))

generator/shellheadergenerator.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,27 @@ void ShellHeaderGenerator::write(QTextStream& s, const AbstractMetaClass* meta_c
305305
s << "enum " << enum1->name() << "{" << endl;
306306
bool first = true;
307307
QString scope = enum1->wasProtected() ? promoterClassName(meta_class) : meta_class->qualifiedCppName();
308+
bool isEnumClass = enum1->typeEntry()->isEnumClass();
309+
if (isEnumClass) {
310+
scope += "::" + enum1->name();
311+
}
308312

309313
for (AbstractMetaEnumValue * value : enum1->values()) {
310314
if (first) { first = false; }
311315
else { s << ", "; }
312-
s << " " << value->name() << " = " << scope << "::" << value->name();
316+
QString assignedValue = scope + "::" + value->name();
317+
if (isEnumClass) {
318+
// prepend value name with class name, the value name on itself could be a duplicate
319+
//
320+
// I thought about creating a enum class instead, and creating an Enum class in PythonQt for the wrapper
321+
// (QMetaEnum has a isScoped method to check for enum classes),
322+
// but the process seemed quite complicated.
323+
s << " " << enum1->name() << "_" << value->name() << " = " << "static_cast<int>(" << scope << "::" << value->name() << ")";
324+
}
325+
else {
326+
s << " " << value->name() << " = " << scope << "::" << value->name();
327+
328+
}
313329
}
314330
s << "};" << endl;
315331
}

generator/typesystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,9 @@ class EnumTypeEntry : public TypeEntry
730730
void addEnumValueRedirection(const QString &rejected, const QString &usedValue);
731731
QString enumValueRedirection(const QString &value) const;
732732

733+
bool isEnumClass() const { return m_enum_class; }
734+
void setEnumClass(bool enum_class) { m_enum_class = enum_class; }
735+
733736
bool forceInteger() const { return m_force_integer; }
734737
void setForceInteger(bool force) { m_force_integer = force; }
735738

@@ -748,6 +751,7 @@ class EnumTypeEntry : public TypeEntry
748751
FlagsTypeEntry *m_flags;
749752

750753
bool m_extensible;
754+
bool m_enum_class;
751755
bool m_force_integer;
752756
};
753757

0 commit comments

Comments
 (0)