mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
Add errors for duplicate properties and blocks
This commit is contained in:
parent
f18c8b7a2d
commit
824476bda1
12 changed files with 122 additions and 0 deletions
|
@ -131,6 +131,16 @@ class AstNode:
|
||||||
yield from child.iterate_children_recursive()
|
yield from child.iterate_children_recursive()
|
||||||
|
|
||||||
|
|
||||||
|
def validate_unique_in_parent(self, error, check=None):
|
||||||
|
for child in self.parent.children:
|
||||||
|
if child is self:
|
||||||
|
break
|
||||||
|
|
||||||
|
if type(child) is type(self):
|
||||||
|
if check is None or check(child):
|
||||||
|
raise CompileError(error)
|
||||||
|
|
||||||
|
|
||||||
def validate(token_name=None, end_token_name=None, skip_incomplete=False):
|
def validate(token_name=None, end_token_name=None, skip_incomplete=False):
|
||||||
""" Decorator for functions that validate an AST node. Exceptions raised
|
""" Decorator for functions that validate an AST node. Exceptions raised
|
||||||
during validation are marked with range information from the tokens. """
|
during validation are marked with range information from the tokens. """
|
||||||
|
|
|
@ -112,6 +112,14 @@ class Property(AstNode):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@validate("name")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate property '{self.tokens['name']}'",
|
||||||
|
check=lambda child: child.tokens["name"] == self.tokens["name"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@docs("name")
|
@docs("name")
|
||||||
def property_docs(self):
|
def property_docs(self):
|
||||||
if self.gir_property is not None:
|
if self.gir_property is not None:
|
||||||
|
|
|
@ -139,6 +139,13 @@ class A11yProperty(BaseTypedAttribute):
|
||||||
did_you_mean=(self.tokens["name"], types.keys()),
|
did_you_mean=(self.tokens["name"], types.keys()),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@validate("name")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate accessibility attribute '{self.tokens['name']}'",
|
||||||
|
check=lambda child: child.tokens["name"] == self.tokens["name"],
|
||||||
|
)
|
||||||
|
|
||||||
@docs("name")
|
@docs("name")
|
||||||
def prop_docs(self):
|
def prop_docs(self):
|
||||||
if self.tokens["name"] in get_types(self.root.gir):
|
if self.tokens["name"] in get_types(self.root.gir):
|
||||||
|
@ -156,6 +163,9 @@ class A11y(AstNode):
|
||||||
def container_is_widget(self):
|
def container_is_widget(self):
|
||||||
validate_parent_type(self, "Gtk", "Widget", "accessibility properties")
|
validate_parent_type(self, "Gtk", "Widget", "accessibility properties")
|
||||||
|
|
||||||
|
@validate("accessibility")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent("Duplicate accessibility block")
|
||||||
|
|
||||||
def emit_xml(self, xml: XmlEmitter):
|
def emit_xml(self, xml: XmlEmitter):
|
||||||
xml.start_tag("accessibility")
|
xml.start_tag("accessibility")
|
||||||
|
|
|
@ -56,6 +56,9 @@ class Items(AstNode):
|
||||||
def container_is_combo_box_text(self):
|
def container_is_combo_box_text(self):
|
||||||
validate_parent_type(self, "Gtk", "ComboBoxText", "combo box items")
|
validate_parent_type(self, "Gtk", "ComboBoxText", "combo box items")
|
||||||
|
|
||||||
|
@validate("items")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent("Duplicate items block")
|
||||||
|
|
||||||
def emit_xml(self, xml: XmlEmitter):
|
def emit_xml(self, xml: XmlEmitter):
|
||||||
xml.start_tag("items")
|
xml.start_tag("items")
|
||||||
|
|
|
@ -27,6 +27,18 @@ class Filters(AstNode):
|
||||||
def container_is_file_filter(self):
|
def container_is_file_filter(self):
|
||||||
validate_parent_type(self, "Gtk", "FileFilter", "file filter properties")
|
validate_parent_type(self, "Gtk", "FileFilter", "file filter properties")
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def unique_in_parent(self):
|
||||||
|
# The token argument to validate() needs to be calculated based on
|
||||||
|
# the instance, hence wrapping it like this.
|
||||||
|
@validate(self.tokens["tag_name"])
|
||||||
|
def wrapped_validator(self):
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate {self.tokens['tag_name']} block",
|
||||||
|
check=lambda child: child.tokens["tag_name"] == self.tokens["tag_name"],
|
||||||
|
)
|
||||||
|
wrapped_validator(self)
|
||||||
|
|
||||||
def emit_xml(self, xml: XmlEmitter):
|
def emit_xml(self, xml: XmlEmitter):
|
||||||
xml.start_tag(self.tokens["tag_name"])
|
xml.start_tag(self.tokens["tag_name"])
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
|
|
|
@ -31,6 +31,13 @@ class LayoutProperty(BaseAttribute):
|
||||||
# there isn't really a way to validate these
|
# there isn't really a way to validate these
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@validate("name")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate layout property '{self.name}'",
|
||||||
|
check=lambda child: child.name == self.name,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
layout_prop = Group(
|
layout_prop = Group(
|
||||||
LayoutProperty,
|
LayoutProperty,
|
||||||
|
@ -53,6 +60,9 @@ class Layout(AstNode):
|
||||||
def container_is_widget(self):
|
def container_is_widget(self):
|
||||||
validate_parent_type(self, "Gtk", "Widget", "layout properties")
|
validate_parent_type(self, "Gtk", "Widget", "layout properties")
|
||||||
|
|
||||||
|
@validate("layout")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent("Duplicate layout block")
|
||||||
|
|
||||||
def emit_xml(self, xml: XmlEmitter):
|
def emit_xml(self, xml: XmlEmitter):
|
||||||
xml.start_tag("layout")
|
xml.start_tag("layout")
|
||||||
|
|
|
@ -55,6 +55,10 @@ class Widgets(AstNode):
|
||||||
def container_is_size_group(self):
|
def container_is_size_group(self):
|
||||||
validate_parent_type(self, "Gtk", "SizeGroup", "size group properties")
|
validate_parent_type(self, "Gtk", "SizeGroup", "size group properties")
|
||||||
|
|
||||||
|
@validate("widgets")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent("Duplicate widgets block")
|
||||||
|
|
||||||
def emit_xml(self, xml: XmlEmitter):
|
def emit_xml(self, xml: XmlEmitter):
|
||||||
xml.start_tag("widgets")
|
xml.start_tag("widgets")
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
|
|
|
@ -51,6 +51,9 @@ class Strings(AstNode):
|
||||||
def container_is_string_list(self):
|
def container_is_string_list(self):
|
||||||
validate_parent_type(self, "Gtk", "StringList", "StringList items")
|
validate_parent_type(self, "Gtk", "StringList", "StringList items")
|
||||||
|
|
||||||
|
@validate("strings")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent("Duplicate strings block")
|
||||||
|
|
||||||
def emit_xml(self, xml: XmlEmitter):
|
def emit_xml(self, xml: XmlEmitter):
|
||||||
xml.start_tag("items")
|
xml.start_tag("items")
|
||||||
|
|
|
@ -41,6 +41,10 @@ class Styles(AstNode):
|
||||||
def container_is_widget(self):
|
def container_is_widget(self):
|
||||||
validate_parent_type(self, "Gtk", "Widget", "style classes")
|
validate_parent_type(self, "Gtk", "Widget", "style classes")
|
||||||
|
|
||||||
|
@validate("styles")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent("Duplicate styles block")
|
||||||
|
|
||||||
def emit_xml(self, xml: XmlEmitter):
|
def emit_xml(self, xml: XmlEmitter):
|
||||||
xml.start_tag("style")
|
xml.start_tag("style")
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
|
|
45
tests/sample_errors/duplicates.blp
Normal file
45
tests/sample_errors/duplicates.blp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
Label {
|
||||||
|
visible: true;
|
||||||
|
visible: false;
|
||||||
|
|
||||||
|
styles [""]
|
||||||
|
styles [""]
|
||||||
|
|
||||||
|
accessibility {
|
||||||
|
label: "label";
|
||||||
|
label: "label";
|
||||||
|
}
|
||||||
|
accessibility {}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileFilter {
|
||||||
|
suffixes []
|
||||||
|
patterns []
|
||||||
|
mime-types []
|
||||||
|
suffixes []
|
||||||
|
patterns []
|
||||||
|
mime-types []
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBoxText {
|
||||||
|
layout {
|
||||||
|
orientation: vertical;
|
||||||
|
orientation: vertical;
|
||||||
|
}
|
||||||
|
layout {}
|
||||||
|
|
||||||
|
items []
|
||||||
|
items []
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeGroup {
|
||||||
|
widgets []
|
||||||
|
widgets []
|
||||||
|
}
|
||||||
|
|
||||||
|
StringList {
|
||||||
|
strings []
|
||||||
|
strings []
|
||||||
|
}
|
12
tests/sample_errors/duplicates.err
Normal file
12
tests/sample_errors/duplicates.err
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
5,3,7,Duplicate property 'visible'
|
||||||
|
8,3,6,Duplicate styles block
|
||||||
|
12,5,5,Duplicate accessibility attribute 'label'
|
||||||
|
14,3,13,Duplicate accessibility block
|
||||||
|
21,3,8,Duplicate suffixes block
|
||||||
|
22,3,8,Duplicate patterns block
|
||||||
|
23,3,10,Duplicate mime-types block
|
||||||
|
29,5,11,Duplicate layout property 'orientation'
|
||||||
|
31,3,6,Duplicate layout block
|
||||||
|
34,3,5,Duplicate items block
|
||||||
|
39,3,7,Duplicate widgets block
|
||||||
|
44,3,7,Duplicate strings block
|
|
@ -179,6 +179,7 @@ class TestSamples(unittest.TestCase):
|
||||||
self.assert_sample_error("consecutive_unexpected_tokens")
|
self.assert_sample_error("consecutive_unexpected_tokens")
|
||||||
self.assert_sample_error("does_not_implement")
|
self.assert_sample_error("does_not_implement")
|
||||||
self.assert_sample_error("duplicate_obj_id")
|
self.assert_sample_error("duplicate_obj_id")
|
||||||
|
self.assert_sample_error("duplicates")
|
||||||
self.assert_sample_error("enum_member_dne")
|
self.assert_sample_error("enum_member_dne")
|
||||||
self.assert_sample_error("filters_in_non_file_filter")
|
self.assert_sample_error("filters_in_non_file_filter")
|
||||||
self.assert_sample_error("gtk_3")
|
self.assert_sample_error("gtk_3")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue