Move bindings out of the Value syntax

They're only valid in properties, so they should just be there. Same
with object values.
This commit is contained in:
James Westman 2023-04-09 18:18:01 -05:00
parent ac2a7d9282
commit 75055ac967
7 changed files with 45 additions and 47 deletions

View file

@ -47,11 +47,6 @@ class Binding(AstNode):
)
return None
@validate("bind")
def not_bindable(self) -> None:
if binding_error := self.context[ValueTypeCtx].binding_error:
raise binding_error
@dataclass
class SimpleBinding:

View file

@ -25,4 +25,3 @@ from .common import *
@dataclass
class ValueTypeCtx:
value_type: T.Optional[GirType]
binding_error: T.Optional[CompileError] = None

View file

@ -22,7 +22,7 @@ from dataclasses import dataclass
from .expression import ExprChain
from .gobject_object import Object
from .gtkbuilder_template import Template
from .values import Value, Translated
from .values import Value, ObjectValue
from .common import *
from .contexts import ValueTypeCtx
from .property_binding import PropertyBinding
@ -30,14 +30,16 @@ from .binding import Binding
class Property(AstNode):
grammar = Statement(UseIdent("name"), ":", Value)
grammar = Statement(
UseIdent("name"), ":", AnyOf(PropertyBinding, Binding, ObjectValue, Value)
)
@property
def name(self) -> str:
return self.tokens["name"]
@property
def value(self) -> Value:
def value(self) -> T.Union[PropertyBinding, Binding, ObjectValue, Value]:
return self.children[0]
@property
@ -49,29 +51,26 @@ class Property(AstNode):
if self.gir_class is not None and not isinstance(self.gir_class, ExternType):
return self.gir_class.properties.get(self.tokens["name"])
@context(ValueTypeCtx)
def value_type(self) -> ValueTypeCtx:
@validate()
def binding_valid(self):
if (
(
isinstance(self.value.child, PropertyBinding)
or isinstance(self.value.child, Binding)
)
(isinstance(self.value, PropertyBinding) or isinstance(self.value, Binding))
and self.gir_property is not None
and self.gir_property.construct_only
):
binding_error = CompileError(
raise CompileError(
f"{self.gir_property.full_name} can't be bound because it is construct-only",
hints=["construct-only properties may only be set to a static value"],
)
else:
binding_error = None
@context(ValueTypeCtx)
def value_type(self) -> ValueTypeCtx:
if self.gir_property is not None:
type = self.gir_property.type
else:
type = None
return ValueTypeCtx(type, binding_error)
return ValueTypeCtx(type)
@validate("name")
def property_exists(self):

View file

@ -121,11 +121,6 @@ class PropertyBinding(AstNode):
f"{gir_class.full_name} does not have a property called {self.property_name}"
)
@validate("bind-property")
def not_bindable(self) -> None:
if binding_error := self.context[ValueTypeCtx].binding_error:
raise binding_error
@validate("bind")
def old_bind(self):
if self.tokens["bind"]:

View file

@ -361,12 +361,12 @@ class ObjectValue(AstNode):
class Value(AstNode):
grammar = AnyOf(PropertyBinding, Binding, Translated, ObjectValue, Flags, Literal)
grammar = AnyOf(Translated, Flags, Literal)
@property
def child(
self,
) -> T.Union[PropertyBinding, Binding, Translated, ObjectValue, Flags, Literal]:
) -> T.Union[Translated, Flags, Literal]:
return self.children[0]

View file

@ -91,48 +91,58 @@ class XmlOutput(OutputFormat):
def _emit_property(self, property: Property, xml: XmlEmitter):
value = property.value
child = value.child
props: T.Dict[str, T.Optional[str]] = {
"name": property.name,
}
if isinstance(child, Translated):
xml.start_tag("property", **props, **self._translated_string_attrs(child))
xml.put_text(child.child.string)
xml.end_tag()
elif isinstance(child, Object):
xml.start_tag("property", **props)
self._emit_object(child, xml)
xml.end_tag()
elif isinstance(child, Binding):
if simple := child.simple_binding:
if isinstance(value, Value):
child = value.child
if isinstance(child, Translated):
xml.start_tag(
"property", **props, **self._translated_string_attrs(child)
)
xml.put_text(child.child.string)
xml.end_tag()
else:
xml.start_tag("property", **props)
self._emit_value(value, xml)
xml.end_tag()
elif isinstance(value, Binding):
if simple := value.simple_binding:
props["bind-source"] = simple.source
props["bind-property"] = simple.property_name
props["bind-flags"] = "sync-create"
xml.put_self_closing("property", **props)
else:
xml.start_tag("binding", **props)
self._emit_expression(child.expression, xml)
self._emit_expression(value.expression, xml)
xml.end_tag()
elif isinstance(child, PropertyBinding):
elif isinstance(value, PropertyBinding):
bind_flags = []
if not child.no_sync_create:
if not value.no_sync_create:
bind_flags.append("sync-create")
if child.inverted:
if value.inverted:
bind_flags.append("invert-boolean")
if child.bidirectional:
if value.bidirectional:
bind_flags.append("bidirectional")
props["bind-source"] = child.source
props["bind-property"] = child.property_name
props["bind-source"] = value.source
props["bind-property"] = value.property_name
props["bind-flags"] = "|".join(bind_flags) or None
xml.put_self_closing("property", **props)
else:
elif isinstance(value, ObjectValue):
xml.start_tag("property", **props)
self._emit_value(value, xml)
self._emit_object(value.object, xml)
xml.end_tag()
else:
raise CompilerBugError()
def _translated_string_attrs(
self, translated: T.Union[QuotedLiteral, Translated]
) -> T.Dict[str, T.Optional[str]]:

View file

@ -1,2 +1,2 @@
4,14,4,ComboBox.has-entry can't be bound because it is construct-only
4,3,34,ComboBox.has-entry can't be bound because it is construct-only
5,3,12,Widget.scale-factor is not writable