Fix flag values

Enums/bitfields have a C identifier, a GLib nick, and a GIR name. The
last two are usually the same except the nick uses '-' and the GIR name
uses '_'. It is confusing.

Blueprint tries to use GIR names for everything, but GTK requires a C
identifier or GLib nick for enum and bitfield values. Blueprint was
sometimes passing the GIR name through instead of finding one of the
other names. Fixed by always emitting the C identifier for enums and
bitfields where the GIR type is known.
This commit is contained in:
James Westman 2022-06-10 13:20:44 -05:00
parent fac311d3c3
commit fd55a5abf2
No known key found for this signature in database
GPG key ID: CE2DBA0ADB654EA6
8 changed files with 27 additions and 18 deletions

View file

@ -122,6 +122,13 @@ class DecompileCtx:
self._blocks_need_end[-1] = _CLOSING[line[-1]] self._blocks_need_end[-1] = _CLOSING[line[-1]]
self._indent += 1 self._indent += 1
def get_enum_value(self, value, type):
for member in type.members.values():
if member.nick == value or member.c_ident == value:
return member.name
return value.replace('-', '_')
def print_attribute(self, name, value, type): def print_attribute(self, name, value, type):
if type is None: if type is None:
@ -142,15 +149,10 @@ class DecompileCtx:
elif type.assignable_to(self.gir.namespaces["Gtk"].lookup_type("GObject.Object")): elif type.assignable_to(self.gir.namespaces["Gtk"].lookup_type("GObject.Object")):
self.print(f"{name}: {value};") self.print(f"{name}: {value};")
elif isinstance(type, Enumeration): elif isinstance(type, Enumeration):
for member in type.members.values(): self.print(f"{name}: {self.get_enum_value(value, type)};")
if member.nick == value or member.c_ident == value:
self.print(f"{name}: {member.name};")
break
else:
self.print(f"{name}: {value.replace('-', '_')};")
elif isinstance(type, Bitfield): elif isinstance(type, Bitfield):
flags = re.sub(r"\s*\|\s*", " | ", value).replace("-", "_") flags = [self.get_enum_value(flag, type) for flag in value.split("|")]
self.print(f"{name}: {flags};") self.print(f"{name}: {' | '.join(flags)};")
else: else:
self.print(f"{name}: \"{escape_quote(value)}\";") self.print(f"{name}: \"{escape_quote(value)}\";")

View file

@ -109,6 +109,13 @@ class LiteralValue(Value):
class Flag(AstNode): class Flag(AstNode):
grammar = UseIdent("value") grammar = UseIdent("value")
@property
def c_ident(self):
if isinstance(self.parent.parent.value_type, gir.Bitfield):
return self.parent.parent.value_type.members[self.tokens["value"]].c_ident
else:
return self.tokens["value"]
@docs() @docs()
def docs(self): def docs(self):
type = self.parent.parent.value_type type = self.parent.parent.value_type
@ -137,15 +144,15 @@ class FlagsValue(Value):
raise CompileError(f"{type.full_name} is not a bitfield type") raise CompileError(f"{type.full_name} is not a bitfield type")
def emit_xml(self, xml: XmlEmitter): def emit_xml(self, xml: XmlEmitter):
xml.put_text("|".join([flag.tokens["value"] for flag in self.children[Flag]])) xml.put_text("|".join([flag.c_ident for flag in self.children[Flag]]))
class IdentValue(Value): class IdentValue(Value):
grammar = UseIdent("value") grammar = UseIdent("value")
def emit_xml(self, xml: XmlEmitter): def emit_xml(self, xml: XmlEmitter):
if isinstance(self.parent.value_type, gir.Enumeration): if isinstance(self.parent.value_type, gir.Enumeration) or isinstance(self.parent.value_type, gir.Bitfield):
xml.put_text(self.parent.value_type.members[self.tokens["value"]].nick) xml.put_text(self.parent.value_type.members[self.tokens["value"]].c_ident)
else: else:
xml.put_text(self.tokens["value"]) xml.put_text(self.tokens["value"])

View file

@ -5,7 +5,7 @@
<accessibility> <accessibility>
<property name="label" translatable="true">Hello, world!</property> <property name="label" translatable="true">Hello, world!</property>
<relation name="labelled-by">my_label</relation> <relation name="labelled-by">my_label</relation>
<state name="checked">true</state> <state name="checked">GTK_ACCESSIBLE_TRISTATE_TRUE</state>
</accessibility> </accessibility>
</object> </object>
<object class="GtkLabel" id="my_label"></object> <object class="GtkLabel" id="my_label"></object>

View file

@ -2,6 +2,6 @@
<interface> <interface>
<requires lib="gtk" version="4.0"/> <requires lib="gtk" version="4.0"/>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="window-placement">top-left</property> <property name="window-placement">GTK_CORNER_TOP_LEFT</property>
</object> </object>
</interface> </interface>

View file

@ -6,5 +6,5 @@ Gio.Application {
} }
EventControllerScroll { EventControllerScroll {
flags: vertical; flags: both_axes;
} }

View file

@ -2,9 +2,9 @@
<interface> <interface>
<requires lib="gtk" version="4.0"/> <requires lib="gtk" version="4.0"/>
<object class="GApplication"> <object class="GApplication">
<property name="flags">is_service|handles_open</property> <property name="flags">G_APPLICATION_IS_SERVICE|G_APPLICATION_HANDLES_OPEN</property>
</object> </object>
<object class="GtkEventControllerScroll"> <object class="GtkEventControllerScroll">
<property name="flags">vertical</property> <property name="flags">GTK_EVENT_CONTROLLER_SCROLL_BOTH_AXES</property>
</object> </object>
</interface> </interface>

View file

@ -2,6 +2,6 @@
<interface> <interface>
<requires lib="gtk" version="4.0"/> <requires lib="gtk" version="4.0"/>
<object class="GtkBox"> <object class="GtkBox">
<property name="orientation">vertical</property> <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
</object> </object>
</interface> </interface>

View file

@ -2,7 +2,7 @@
<interface> <interface>
<requires lib="gtk" version="4.0"/> <requires lib="gtk" version="4.0"/>
<object class="GtkSizeGroup"> <object class="GtkSizeGroup">
<property name="mode">horizontal</property> <property name="mode">GTK_SIZE_GROUP_HORIZONTAL</property>
<widgets> <widgets>
<widget name="label"/> <widget name="label"/>
<widget name="button"/> <widget name="button"/>