From f1e1811e1f6662b216314f2f1b6488fe04ebac94 Mon Sep 17 00:00:00 2001 From: James Westman Date: Fri, 12 Nov 2021 18:01:56 -0600 Subject: [PATCH] Improved validation --- gtkblueprinttool/ast_utils.py | 6 ++++++ gtkblueprinttool/extensions/gtk_a11y.py | 5 +---- gtkblueprinttool/extensions/gtk_file_filter.py | 8 ++++++-- gtkblueprinttool/extensions/gtk_layout.py | 5 +---- gtkblueprinttool/extensions/gtk_size_group.py | 6 +++++- gtkblueprinttool/extensions/gtk_styles.py | 8 ++++++-- tests/sample_errors/filters_in_non_file_filter.blp | 7 +++++++ tests/sample_errors/filters_in_non_file_filter.err | 3 +++ tests/sample_errors/styles_in_non_widget.blp | 6 ++++++ tests/sample_errors/styles_in_non_widget.err | 1 + tests/sample_errors/widgets_in_non_size_group.blp | 5 +++++ tests/sample_errors/widgets_in_non_size_group.err | 1 + tests/test_samples.py | 3 +++ 13 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 tests/sample_errors/filters_in_non_file_filter.blp create mode 100644 tests/sample_errors/filters_in_non_file_filter.err create mode 100644 tests/sample_errors/styles_in_non_widget.blp create mode 100644 tests/sample_errors/styles_in_non_widget.err create mode 100644 tests/sample_errors/widgets_in_non_size_group.blp create mode 100644 tests/sample_errors/widgets_in_non_size_group.err diff --git a/gtkblueprinttool/ast_utils.py b/gtkblueprinttool/ast_utils.py index 169465a..d1da93c 100644 --- a/gtkblueprinttool/ast_utils.py +++ b/gtkblueprinttool/ast_utils.py @@ -72,6 +72,12 @@ class AstNode: else: return self.parent.parent_by_type(type) + def validate_parent_type(self, ns: str, name: str, err_msg: str): + parent = self.root.gir.get_type(name, ns) + container_type = self.parent_by_type(ast.Object).gir_class + if container_type and not container_type.assignable_to(parent): + raise CompileError(f"{container_type.full_name} is not a {parent.full_name}, so it doesn't have {err_msg}") + @lazy_prop def errors(self): return list(self._get_errors()) diff --git a/gtkblueprinttool/extensions/gtk_a11y.py b/gtkblueprinttool/extensions/gtk_a11y.py index 6fb834b..3d99655 100644 --- a/gtkblueprinttool/extensions/gtk_a11y.py +++ b/gtkblueprinttool/extensions/gtk_a11y.py @@ -108,10 +108,7 @@ def _get_docs(gir, name): class A11y(AstNode): @validate("accessibility") def container_is_widget(self): - widget = self.root.gir.get_type("Widget", "Gtk") - container_type = self.parent_by_type(ast.Object).gir_class - if container_type and not container_type.assignable_to(widget): - raise CompileError(f"{container_type.full_name} is not a {widget.full_name}, so it doesn't have accessibility properties") + self.validate_parent_type("Gtk", "Widget", "accessibility properties") def emit_xml(self, xml: XmlEmitter): diff --git a/gtkblueprinttool/extensions/gtk_file_filter.py b/gtkblueprinttool/extensions/gtk_file_filter.py index 5d809b4..6e696bf 100644 --- a/gtkblueprinttool/extensions/gtk_file_filter.py +++ b/gtkblueprinttool/extensions/gtk_file_filter.py @@ -19,7 +19,7 @@ from .. import ast -from ..ast_utils import AstNode +from ..ast_utils import AstNode, validate from ..completions_utils import * from ..lsp_utils import Completion, CompletionItemKind from ..parse_tree import * @@ -28,6 +28,10 @@ from ..xml_emitter import XmlEmitter class Filters(AstNode): + @validate() + def container_is_file_filter(self): + self.validate_parent_type("Gtk", "FileFilter", "file filter properties") + def emit_xml(self, xml: XmlEmitter): xml.start_tag(self.tokens["tag_name"]) for child in self.children: @@ -46,7 +50,7 @@ def create_node(tag_name: str, singular: str): return Group( Filters, Statement( - Keyword(tag_name), + Keyword(tag_name, True), UseLiteral("tag_name", tag_name), OpenBracket(), Delimited( diff --git a/gtkblueprinttool/extensions/gtk_layout.py b/gtkblueprinttool/extensions/gtk_layout.py index 9ef05e5..2c43686 100644 --- a/gtkblueprinttool/extensions/gtk_layout.py +++ b/gtkblueprinttool/extensions/gtk_layout.py @@ -30,10 +30,7 @@ from ..xml_emitter import XmlEmitter class Layout(AstNode): @validate("layout") def container_is_widget(self): - widget = self.root.gir.get_type("Widget", "Gtk") - container_type = self.parent_by_type(ast.Object).gir_class - if container_type and not container_type.assignable_to(widget): - raise CompileError(f"{container_type.full_name} is not a {widget.full_name}, so it doesn't have layout properties") + self.validate_parent_type("Gtk", "Widget", "layout properties") def emit_xml(self, xml: XmlEmitter): diff --git a/gtkblueprinttool/extensions/gtk_size_group.py b/gtkblueprinttool/extensions/gtk_size_group.py index 6368c37..f2ca9d8 100644 --- a/gtkblueprinttool/extensions/gtk_size_group.py +++ b/gtkblueprinttool/extensions/gtk_size_group.py @@ -28,6 +28,10 @@ from ..xml_emitter import XmlEmitter class Widgets(AstNode): + @validate("widgets") + def container_is_size_group(self): + self.validate_parent_type("Gtk", "SizeGroup", "size group properties") + def emit_xml(self, xml: XmlEmitter): xml.start_tag("widgets") for child in self.children: @@ -57,7 +61,7 @@ class Widget(AstNode): widgets = Group( Widgets, Statement( - Keyword("widgets"), + Keyword("widgets", True), OpenBracket(), Delimited( Group( diff --git a/gtkblueprinttool/extensions/gtk_styles.py b/gtkblueprinttool/extensions/gtk_styles.py index b29cefd..04153a5 100644 --- a/gtkblueprinttool/extensions/gtk_styles.py +++ b/gtkblueprinttool/extensions/gtk_styles.py @@ -19,7 +19,7 @@ from .. import ast -from ..ast_utils import AstNode +from ..ast_utils import AstNode, validate from ..completions_utils import * from ..lsp_utils import Completion, CompletionItemKind from ..parse_tree import * @@ -28,6 +28,10 @@ from ..xml_emitter import XmlEmitter class Styles(AstNode): + @validate("styles") + def container_is_widget(self): + self.validate_parent_type("Gtk", "Widget", "style classes") + def emit_xml(self, xml: XmlEmitter): xml.start_tag("style") for child in self.children: @@ -43,7 +47,7 @@ class StyleClass(AstNode): styles = Group( Styles, Statement( - Keyword("styles"), + Keyword("styles", True), OpenBracket(), Delimited( Group( diff --git a/tests/sample_errors/filters_in_non_file_filter.blp b/tests/sample_errors/filters_in_non_file_filter.blp new file mode 100644 index 0000000..44e6d49 --- /dev/null +++ b/tests/sample_errors/filters_in_non_file_filter.blp @@ -0,0 +1,7 @@ +using Gtk 4.0; + +Widget { + mime-types []; + patterns []; + suffixes []; +} diff --git a/tests/sample_errors/filters_in_non_file_filter.err b/tests/sample_errors/filters_in_non_file_filter.err new file mode 100644 index 0000000..018503f --- /dev/null +++ b/tests/sample_errors/filters_in_non_file_filter.err @@ -0,0 +1,3 @@ +4,3,14,Gtk.Widget is not a Gtk.FileFilter, so it doesn't have file filter properties +5,3,12,Gtk.Widget is not a Gtk.FileFilter, so it doesn't have file filter properties +6,3,12,Gtk.Widget is not a Gtk.FileFilter, so it doesn't have file filter properties diff --git a/tests/sample_errors/styles_in_non_widget.blp b/tests/sample_errors/styles_in_non_widget.blp new file mode 100644 index 0000000..816d4a9 --- /dev/null +++ b/tests/sample_errors/styles_in_non_widget.blp @@ -0,0 +1,6 @@ +using Gtk 4.0; +using GObject 2.0; + +GObject.Object { + styles []; +} diff --git a/tests/sample_errors/styles_in_non_widget.err b/tests/sample_errors/styles_in_non_widget.err new file mode 100644 index 0000000..4c59ffd --- /dev/null +++ b/tests/sample_errors/styles_in_non_widget.err @@ -0,0 +1 @@ +5,3,6,GObject.Object is not a Gtk.Widget, so it doesn't have style classes diff --git a/tests/sample_errors/widgets_in_non_size_group.blp b/tests/sample_errors/widgets_in_non_size_group.blp new file mode 100644 index 0000000..82886a1 --- /dev/null +++ b/tests/sample_errors/widgets_in_non_size_group.blp @@ -0,0 +1,5 @@ +using Gtk 4.0; + +Widget { + widgets []; +} diff --git a/tests/sample_errors/widgets_in_non_size_group.err b/tests/sample_errors/widgets_in_non_size_group.err new file mode 100644 index 0000000..70ce8fb --- /dev/null +++ b/tests/sample_errors/widgets_in_non_size_group.err @@ -0,0 +1 @@ +4,3,7,Gtk.Widget is not a Gtk.SizeGroup, so it doesn't have size group properties diff --git a/tests/test_samples.py b/tests/test_samples.py index ebf415a..1e73cc4 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -120,6 +120,7 @@ class TestSamples(unittest.TestCase): self.assert_sample_error("class_dne") self.assert_sample_error("duplicate_obj_id") self.assert_sample_error("enum_member_dne") + self.assert_sample_error("filters_in_non_file_filter") self.assert_sample_error("invalid_bool") self.assert_sample_error("layout_in_non_widget") self.assert_sample_error("ns_not_imported") @@ -130,5 +131,7 @@ class TestSamples(unittest.TestCase): self.assert_sample_error("signal_dne") self.assert_sample_error("size_group_non_widget") self.assert_sample_error("size_group_obj_dne") + self.assert_sample_error("styles_in_non_widget") self.assert_sample_error("two_templates") self.assert_sample_error("using_invalid_namespace") + self.assert_sample_error("widgets_in_non_size_group")