From 51d8969ced0bcee74b9d204d500d4b8b87faa7ee Mon Sep 17 00:00:00 2001 From: James Westman Date: Mon, 19 Dec 2022 14:36:32 -0600 Subject: [PATCH] Fix menus - Menus require an ID - The top level menu block can't have attributes --- blueprintcompiler/language/gtk_menu.py | 27 ++++++++++++++++++- tests/sample_errors/menu_no_id.blp | 3 +++ tests/sample_errors/menu_no_id.err | 1 + .../sample_errors/menu_toplevel_attribute.blp | 5 ++++ .../sample_errors/menu_toplevel_attribute.err | 2 ++ tests/samples/menu.blp | 5 +--- tests/samples/menu.ui | 4 +-- tests/samples/menu_dec.blp | 5 +--- tests/test_samples.py | 4 ++- 9 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 tests/sample_errors/menu_no_id.blp create mode 100644 tests/sample_errors/menu_no_id.err create mode 100644 tests/sample_errors/menu_toplevel_attribute.blp create mode 100644 tests/sample_errors/menu_toplevel_attribute.err diff --git a/blueprintcompiler/language/gtk_menu.py b/blueprintcompiler/language/gtk_menu.py index 3d3e6ee..73aa039 100644 --- a/blueprintcompiler/language/gtk_menu.py +++ b/blueprintcompiler/language/gtk_menu.py @@ -39,6 +39,11 @@ class Menu(AstNode): def tag(self) -> str: return self.tokens["tag"] + @validate("menu") + def has_id(self): + if self.tokens["tag"] == "menu" and self.tokens["id"] is None: + raise CompileError("Menu requires an ID") + class MenuAttribute(BaseAttribute): tag_name = "attribute" @@ -137,7 +142,27 @@ menu_contents.children = [ menu: Group = Group( Menu, - ["menu", UseLiteral("tag", "menu"), Optional(UseIdent("id")), menu_contents], + [ + Keyword("menu"), + UseLiteral("tag", "menu"), + Optional(UseIdent("id")), + [ + Match("{"), + Until( + AnyOf( + menu_section, + menu_submenu, + menu_item_shorthand, + menu_item, + Fail( + menu_attribute, + "Attributes are not permitted at the top level of a menu", + ), + ), + "}", + ), + ], + ], ) from .ui import UI diff --git a/tests/sample_errors/menu_no_id.blp b/tests/sample_errors/menu_no_id.blp new file mode 100644 index 0000000..5f6396e --- /dev/null +++ b/tests/sample_errors/menu_no_id.blp @@ -0,0 +1,3 @@ +using Gtk 4.0; + +menu {} \ No newline at end of file diff --git a/tests/sample_errors/menu_no_id.err b/tests/sample_errors/menu_no_id.err new file mode 100644 index 0000000..e97f033 --- /dev/null +++ b/tests/sample_errors/menu_no_id.err @@ -0,0 +1 @@ +3,1,4,Menu requires an ID \ No newline at end of file diff --git a/tests/sample_errors/menu_toplevel_attribute.blp b/tests/sample_errors/menu_toplevel_attribute.blp new file mode 100644 index 0000000..21ceeff --- /dev/null +++ b/tests/sample_errors/menu_toplevel_attribute.blp @@ -0,0 +1,5 @@ +using Gtk 4.0; + +menu { + not-allowed: true; +} \ No newline at end of file diff --git a/tests/sample_errors/menu_toplevel_attribute.err b/tests/sample_errors/menu_toplevel_attribute.err new file mode 100644 index 0000000..45713cf --- /dev/null +++ b/tests/sample_errors/menu_toplevel_attribute.err @@ -0,0 +1,2 @@ +4,5,19,Attributes are not permitted at the top level of a menu +4,16,8,Unexpected tokens \ No newline at end of file diff --git a/tests/samples/menu.blp b/tests/samples/menu.blp index f15dbdb..4c52bab 100644 --- a/tests/samples/menu.blp +++ b/tests/samples/menu.blp @@ -1,9 +1,6 @@ using Gtk 4.0; -menu { - label: _("menu label"); - test-custom-attribute: 3.1415; - +menu my-menu { submenu { section { label: "test section"; diff --git a/tests/samples/menu.ui b/tests/samples/menu.ui index a84fa57..3ba1fed 100644 --- a/tests/samples/menu.ui +++ b/tests/samples/menu.ui @@ -1,9 +1,7 @@ - - menu label - 3.1415 +
test section diff --git a/tests/samples/menu_dec.blp b/tests/samples/menu_dec.blp index bc4ddf1..64a6021 100644 --- a/tests/samples/menu_dec.blp +++ b/tests/samples/menu_dec.blp @@ -1,9 +1,6 @@ using Gtk 4.0; -menu { - label: _("menu label"); - test-custom-attribute: "3.1415"; - +menu my-menu { submenu { section { label: "test section"; diff --git a/tests/test_samples.py b/tests/test_samples.py index c745226..279ceb6 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -156,7 +156,7 @@ class TestSamples(unittest.TestCase): self.assert_sample("flags", skip_run=True) # TODO: Fix self.assert_sample("id_prop") self.assert_sample("layout") - self.assert_sample("menu", skip_run=True) # TODO: Fix + self.assert_sample("menu") self.assert_sample("numbers") self.assert_sample("object_prop") self.assert_sample( @@ -213,6 +213,8 @@ class TestSamples(unittest.TestCase): self.assert_sample_error("inline_menu") self.assert_sample_error("invalid_bool") self.assert_sample_error("layout_in_non_widget") + self.assert_sample_error("menu_no_id") + self.assert_sample_error("menu_toplevel_attribute") self.assert_sample_error("no_import_version") self.assert_sample_error("ns_not_imported") self.assert_sample_error("not_a_class")