mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
More errors for duplicates
This commit is contained in:
parent
2ca71de061
commit
6ac798ea6f
13 changed files with 105 additions and 9 deletions
|
@ -175,7 +175,9 @@ class AstNode:
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
yield from child.get_semantic_tokens()
|
yield from child.get_semantic_tokens()
|
||||||
|
|
||||||
def validate_unique_in_parent(self, error, check=None):
|
def validate_unique_in_parent(
|
||||||
|
self, error: str, check: T.Optional[T.Callable[["AstNode"], bool]] = None
|
||||||
|
):
|
||||||
for child in self.parent.children:
|
for child in self.parent.children:
|
||||||
if child is self:
|
if child is self:
|
||||||
break
|
break
|
||||||
|
|
|
@ -24,6 +24,23 @@ from .contexts import ScopeCtx
|
||||||
from .common import *
|
from .common import *
|
||||||
|
|
||||||
|
|
||||||
|
class SignalFlag(AstNode):
|
||||||
|
grammar = AnyOf(
|
||||||
|
UseExact("flag", "swapped"),
|
||||||
|
UseExact("flag", "after"),
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def flag(self) -> str:
|
||||||
|
return self.tokens["flag"]
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def unique(self):
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate flag '{self.flag}'", lambda x: x.flag == self.flag
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Signal(AstNode):
|
class Signal(AstNode):
|
||||||
grammar = Statement(
|
grammar = Statement(
|
||||||
UseIdent("name"),
|
UseIdent("name"),
|
||||||
|
@ -39,12 +56,7 @@ class Signal(AstNode):
|
||||||
Match("(").expected("argument list"),
|
Match("(").expected("argument list"),
|
||||||
Optional(UseIdent("object")).expected("object identifier"),
|
Optional(UseIdent("object")).expected("object identifier"),
|
||||||
Match(")").expected(),
|
Match(")").expected(),
|
||||||
ZeroOrMore(
|
ZeroOrMore(SignalFlag),
|
||||||
AnyOf(
|
|
||||||
[Keyword("swapped"), UseLiteral("swapped", True)],
|
|
||||||
[Keyword("after"), UseLiteral("after", True)],
|
|
||||||
)
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -55,6 +67,13 @@ class Signal(AstNode):
|
||||||
def detail_name(self) -> T.Optional[str]:
|
def detail_name(self) -> T.Optional[str]:
|
||||||
return self.tokens["detail_name"]
|
return self.tokens["detail_name"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def full_name(self) -> str:
|
||||||
|
if self.detail_name is None:
|
||||||
|
return self.name
|
||||||
|
else:
|
||||||
|
return self.name + "::" + self.detail_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def handler(self) -> str:
|
def handler(self) -> str:
|
||||||
return self.tokens["handler"]
|
return self.tokens["handler"]
|
||||||
|
@ -63,13 +82,17 @@ class Signal(AstNode):
|
||||||
def object_id(self) -> T.Optional[str]:
|
def object_id(self) -> T.Optional[str]:
|
||||||
return self.tokens["object"]
|
return self.tokens["object"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def flags(self) -> T.List[SignalFlag]:
|
||||||
|
return self.children[SignalFlag]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_swapped(self) -> bool:
|
def is_swapped(self) -> bool:
|
||||||
return self.tokens["swapped"] or False
|
return any(x.flag == "swapped" for x in self.flags)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_after(self) -> bool:
|
def is_after(self) -> bool:
|
||||||
return self.tokens["after"] or False
|
return any(x.flag == "after" for x in self.flags)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def gir_signal(self):
|
def gir_signal(self):
|
||||||
|
|
|
@ -38,6 +38,13 @@ class Item(AstNode):
|
||||||
def value(self) -> StringValue:
|
def value(self) -> StringValue:
|
||||||
return self.children[StringValue][0]
|
return self.children[StringValue][0]
|
||||||
|
|
||||||
|
@validate("name")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
if self.name is not None:
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate item '{self.name}'", lambda x: x.name == self.name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ExtComboBoxItems(AstNode):
|
class ExtComboBoxItems(AstNode):
|
||||||
grammar = [
|
grammar = [
|
||||||
|
|
|
@ -46,6 +46,13 @@ class FilterString(AstNode):
|
||||||
def item(self) -> str:
|
def item(self) -> str:
|
||||||
return self.tokens["name"]
|
return self.tokens["name"]
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate {self.tokens['tag_name']} '{self.item}'",
|
||||||
|
check=lambda child: child.item == self.item,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_node(tag_name: str, singular: str):
|
def create_node(tag_name: str, singular: str):
|
||||||
return Group(
|
return Group(
|
||||||
|
|
|
@ -29,6 +29,10 @@ class ExtListItemFactory(AstNode):
|
||||||
"sub-templates",
|
"sub-templates",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@validate("template")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent("Duplicate template block")
|
||||||
|
|
||||||
@validate()
|
@validate()
|
||||||
def type_is_list_item(self):
|
def type_is_list_item(self):
|
||||||
if self.type_name is not None:
|
if self.type_name is not None:
|
||||||
|
|
|
@ -69,6 +69,12 @@ class MenuAttribute(AstNode):
|
||||||
def value_type(self) -> ValueTypeCtx:
|
def value_type(self) -> ValueTypeCtx:
|
||||||
return ValueTypeCtx(None)
|
return ValueTypeCtx(None)
|
||||||
|
|
||||||
|
@validate("name")
|
||||||
|
def unique(self):
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate attribute '{self.name}'", lambda x: x.name == self.name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
menu_child = AnyOf()
|
menu_child = AnyOf()
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,12 @@ class Widget(AstNode):
|
||||||
f"Cannot assign {object.gir_class.full_name} to {type.full_name}"
|
f"Cannot assign {object.gir_class.full_name} to {type.full_name}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@validate("name")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Object '{self.name}' is listed twice", lambda x: x.name == self.name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ExtSizeGroupWidgets(AstNode):
|
class ExtSizeGroupWidgets(AstNode):
|
||||||
grammar = [
|
grammar = [
|
||||||
|
|
|
@ -29,6 +29,12 @@ class StyleClass(AstNode):
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
return self.tokens["name"]
|
return self.tokens["name"]
|
||||||
|
|
||||||
|
@validate("name")
|
||||||
|
def unique_in_parent(self):
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate style class '{self.name}'", lambda x: x.name == self.name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ExtStyles(AstNode):
|
class ExtStyles(AstNode):
|
||||||
grammar = [
|
grammar = [
|
||||||
|
|
|
@ -112,6 +112,20 @@ class Child(AstNode):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def internal_child_unique(self):
|
||||||
|
if self.annotation is not None:
|
||||||
|
if isinstance(self.annotation.child, ChildInternal):
|
||||||
|
internal_child = self.annotation.child.internal_child
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate internal child '{internal_child}'",
|
||||||
|
lambda x: (
|
||||||
|
x.annotation
|
||||||
|
and isinstance(x.annotation.child, ChildInternal)
|
||||||
|
and x.annotation.child.internal_child == internal_child
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@decompiler("child")
|
@decompiler("child")
|
||||||
def decompile_child(ctx, gir, type=None, internal_child=None):
|
def decompile_child(ctx, gir, type=None, internal_child=None):
|
||||||
|
|
|
@ -44,6 +44,12 @@ class PropertyBindingFlag(AstNode):
|
||||||
actions=[CodeAction("remove 'sync-create'", "")],
|
actions=[CodeAction("remove 'sync-create'", "")],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def unique(self):
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate flag '{self.flag}'", lambda x: x.flag == self.flag
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class PropertyBinding(AstNode):
|
class PropertyBinding(AstNode):
|
||||||
grammar = AnyOf(
|
grammar = AnyOf(
|
||||||
|
|
|
@ -229,6 +229,12 @@ class Flag(AstNode):
|
||||||
did_you_mean=(self.tokens["value"], expected_type.members.keys()),
|
did_you_mean=(self.tokens["value"], expected_type.members.keys()),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def unique(self):
|
||||||
|
self.validate_unique_in_parent(
|
||||||
|
f"Duplicate flag '{self.name}'", lambda x: x.name == self.name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Flags(AstNode):
|
class Flags(AstNode):
|
||||||
grammar = [Flag, "|", Flag, ZeroOrMore(["|", Flag])]
|
grammar = [Flag, "|", Flag, ZeroOrMore(["|", Flag])]
|
||||||
|
|
8
tests/sample_errors/duplicate_internal_child.blp
Normal file
8
tests/sample_errors/duplicate_internal_child.blp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
$MyWidget {
|
||||||
|
[internal-child test]
|
||||||
|
Button {}
|
||||||
|
[internal-child test]
|
||||||
|
Button {}
|
||||||
|
}
|
1
tests/sample_errors/duplicate_internal_child.err
Normal file
1
tests/sample_errors/duplicate_internal_child.err
Normal file
|
@ -0,0 +1 @@
|
||||||
|
6,3,33,Duplicate internal child 'test'
|
Loading…
Add table
Add a link
Reference in a new issue