diff --git a/blueprintcompiler/language/gtkbuilder_child.py b/blueprintcompiler/language/gtkbuilder_child.py index 83fadf7..72843a1 100644 --- a/blueprintcompiler/language/gtkbuilder_child.py +++ b/blueprintcompiler/language/gtkbuilder_child.py @@ -24,6 +24,10 @@ from .gobject_object import Object from .response_id import ResponseId from .common import * +ALLOWED_PARENTS: T.List[T.Tuple[str, str]] = [ + ("Gtk", "Buildable"), + ("Gio", "ListStore") +] class Child(AstNode): grammar = [ @@ -37,6 +41,22 @@ class Child(AstNode): Object, ] + @validate() + def parent_can_have_child(self): + if gir_class := self.parent.gir_class: + for namespace, name in ALLOWED_PARENTS: + parent_type = self.root.gir.get_type(name, namespace) + if gir_class.assignable_to(parent_type): + break + else: + hints=["only Gio.ListStore or Gtk.Buildable implementors can have children"] + if "child" in gir_class.properties: + hints.append("did you mean to assign this object to the 'child' property?") + raise CompileError( + f"{gir_class.full_name} doesn't have children", + hints=hints, + ) + @cached_property def response_id(self) -> T.Optional[ResponseId]: """Get action widget's response ID. diff --git a/tests/sample_errors/children.blp b/tests/sample_errors/children.blp new file mode 100644 index 0000000..400fe2d --- /dev/null +++ b/tests/sample_errors/children.blp @@ -0,0 +1,5 @@ +using Gtk 4.0; + +ListItem { + Label {} +} \ No newline at end of file diff --git a/tests/sample_errors/children.err b/tests/sample_errors/children.err new file mode 100644 index 0000000..d294464 --- /dev/null +++ b/tests/sample_errors/children.err @@ -0,0 +1 @@ +4,3,8,Gtk.ListItem doesn't have children \ No newline at end of file diff --git a/tests/test_samples.py b/tests/test_samples.py index ea6b2ea..4fdb5c0 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -175,6 +175,7 @@ class TestSamples(unittest.TestCase): self.assert_sample_error("action_widget_response_dne") self.assert_sample_error("action_widget_negative_response") self.assert_sample_error("bitfield_member_dne") + self.assert_sample_error("children") self.assert_sample_error("class_assign") self.assert_sample_error("class_dne") self.assert_sample_error("consecutive_unexpected_tokens")