Format using black

This commit is contained in:
James Westman 2022-12-19 11:49:10 -06:00
parent 6a36d92380
commit 8fee46ec68
No known key found for this signature in database
GPG key ID: CE2DBA0ADB654EA6
40 changed files with 975 additions and 610 deletions

View file

@ -16,7 +16,16 @@ from .gtkbuilder_template import Template
from .imports import GtkDirective, Import
from .ui import UI
from .types import ClassName
from .values import TypeValue, IdentValue, TranslatedStringValue, FlagsValue, Flag, QuotedValue, NumberValue, Value
from .values import (
TypeValue,
IdentValue,
TranslatedStringValue,
FlagsValue,
Flag,
QuotedValue,
NumberValue,
Value,
)
from .common import *

View file

@ -23,7 +23,7 @@ from .common import *
class BaseAttribute(AstNode):
""" A helper class for attribute syntax of the form `name: literal_value;`"""
"""A helper class for attribute syntax of the form `name: literal_value;`"""
tag_name: str = ""
attr_name: str = "name"
@ -34,5 +34,5 @@ class BaseAttribute(AstNode):
class BaseTypedAttribute(BaseAttribute):
""" A BaseAttribute whose parent has a value_type property that can assist
in validation. """
"""A BaseAttribute whose parent has a value_type property that can assist
in validation."""

View file

@ -33,6 +33,7 @@ class ObjectContent(AstNode):
def gir_class(self):
return self.parent.gir_class
class Object(AstNode):
grammar: T.Any = [
ConcreteClassName,
@ -75,13 +76,17 @@ def validate_parent_type(node, ns: str, name: str, err_msg: str):
parent = node.root.gir.get_type(name, ns)
container_type = node.parent_by_type(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}")
raise CompileError(
f"{container_type.full_name} is not a {parent.full_name}, so it doesn't have {err_msg}"
)
@decompiler("object")
def decompile_object(ctx, gir, klass, id=None):
gir_class = ctx.type_by_cname(klass)
klass_name = decompile.full_name(gir_class) if gir_class is not None else "." + klass
klass_name = (
decompile.full_name(gir_class) if gir_class is not None else "." + klass
)
if id is None:
ctx.print(f"{klass_name} {{")
else:

View file

@ -34,12 +34,16 @@ class Property(AstNode):
UseIdent("bind_source"),
".",
UseIdent("bind_property"),
ZeroOrMore(AnyOf(
["no-sync-create", UseLiteral("no_sync_create", True)],
["inverted", UseLiteral("inverted", True)],
["bidirectional", UseLiteral("bidirectional", True)],
Match("sync-create").warn("sync-create is deprecated in favor of no-sync-create"),
)),
ZeroOrMore(
AnyOf(
["no-sync-create", UseLiteral("no_sync_create", True)],
["inverted", UseLiteral("inverted", True)],
["bidirectional", UseLiteral("bidirectional", True)],
Match("sync-create").warn(
"sync-create is deprecated in favor of no-sync-create"
),
)
),
";",
],
Statement(
@ -63,19 +67,16 @@ class Property(AstNode):
def gir_class(self):
return self.parent.parent.gir_class
@property
def gir_property(self):
if self.gir_class is not None:
return self.gir_class.properties.get(self.tokens["name"])
@property
def value_type(self):
if self.gir_property is not None:
return self.gir_property.type
@validate("name")
def property_exists(self):
if self.gir_class is None:
@ -91,15 +92,19 @@ class Property(AstNode):
if self.gir_property is None:
raise CompileError(
f"Class {self.gir_class.full_name} does not contain a property called {self.tokens['name']}",
did_you_mean=(self.tokens["name"], self.gir_class.properties.keys())
did_you_mean=(self.tokens["name"], self.gir_class.properties.keys()),
)
@validate("bind")
def property_bindable(self):
if self.tokens["bind"] and self.gir_property is not None and self.gir_property.construct_only:
if (
self.tokens["bind"]
and self.gir_property is not None
and self.gir_property.construct_only
):
raise CompileError(
f"{self.gir_property.full_name} can't be bound because it is construct-only",
hints=["construct-only properties may only be set to a static value"]
hints=["construct-only properties may only be set to a static value"],
)
@validate("name")
@ -107,7 +112,6 @@ class Property(AstNode):
if self.gir_property is not None and not self.gir_property.writable:
raise CompileError(f"{self.gir_property.full_name} is not writable")
@validate()
def obj_property_type(self):
if len(self.children[Object]) == 0:
@ -115,20 +119,23 @@ class Property(AstNode):
object = self.children[Object][0]
type = self.value_type
if object and type and object.gir_class and not object.gir_class.assignable_to(type):
if (
object
and type
and object.gir_class
and not object.gir_class.assignable_to(type)
):
raise CompileError(
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"Duplicate property '{self.tokens['name']}'",
check=lambda child: child.tokens["name"] == self.tokens["name"]
check=lambda child: child.tokens["name"] == self.tokens["name"],
)
@docs("name")
def property_docs(self):
if self.gir_property is not None:

View file

@ -26,19 +26,23 @@ from .common import *
class Signal(AstNode):
grammar = Statement(
UseIdent("name"),
Optional([
"::",
UseIdent("detail_name").expected("a signal detail name"),
]),
Optional(
[
"::",
UseIdent("detail_name").expected("a signal detail name"),
]
),
"=>",
UseIdent("handler").expected("the name of a function to handle the signal"),
Match("(").expected("argument list"),
Optional(UseIdent("object")).expected("object identifier"),
Match(")").expected(),
ZeroOrMore(AnyOf(
[Keyword("swapped"), UseLiteral("swapped", True)],
[Keyword("after"), UseLiteral("after", True)],
)),
ZeroOrMore(
AnyOf(
[Keyword("swapped"), UseLiteral("swapped", True)],
[Keyword("after"), UseLiteral("after", True)],
)
),
)
@property
@ -65,18 +69,15 @@ class Signal(AstNode):
def is_after(self) -> bool:
return self.tokens["after"] or False
@property
def gir_signal(self):
if self.gir_class is not None:
return self.gir_class.signals.get(self.tokens["name"])
@property
def gir_class(self):
return self.parent.parent.gir_class
@validate("name")
def signal_exists(self):
if self.gir_class is None:
@ -92,10 +93,9 @@ class Signal(AstNode):
if self.gir_signal is None:
raise CompileError(
f"Class {self.gir_class.full_name} does not contain a signal called {self.tokens['name']}",
did_you_mean=(self.tokens["name"], self.gir_class.signals.keys())
did_you_mean=(self.tokens["name"], self.gir_class.signals.keys()),
)
@validate("object")
def object_exists(self):
object_id = self.tokens["object"]
@ -103,10 +103,7 @@ class Signal(AstNode):
return
if self.root.objects_by_id.get(object_id) is None:
raise CompileError(
f"Could not find object with ID '{object_id}'"
)
raise CompileError(f"Could not find object with ID '{object_id}'")
@docs("name")
def signal_docs(self):

View file

@ -86,6 +86,7 @@ def get_state_types(gir):
"selected": BoolType(),
}
def get_types(gir):
return {
**get_property_types(gir),
@ -93,6 +94,7 @@ def get_types(gir):
**get_state_types(gir),
}
def _get_docs(gir, name):
if gir_type := (
gir.get_type("AccessibleProperty", "Gtk").members.get(name)
@ -174,8 +176,7 @@ class A11y(AstNode):
)
def a11y_completer(ast_node, match_variables):
yield Completion(
"accessibility", CompletionItemKind.Snippet,
snippet="accessibility {\n $0\n}"
"accessibility", CompletionItemKind.Snippet, snippet="accessibility {\n $0\n}"
)
@ -185,20 +186,24 @@ def a11y_completer(ast_node, match_variables):
)
def a11y_name_completer(ast_node, match_variables):
for name, type in get_types(ast_node.root.gir).items():
yield Completion(name, CompletionItemKind.Property, docs=_get_docs(ast_node.root.gir, type))
yield Completion(
name, CompletionItemKind.Property, docs=_get_docs(ast_node.root.gir, type)
)
@decompiler("relation", cdata=True)
def decompile_relation(ctx, gir, name, cdata):
ctx.print_attribute(name, cdata, get_types(ctx.gir).get(name))
@decompiler("state", cdata=True)
def decompile_state(ctx, gir, name, cdata, translatable="false"):
if decompile.truthy(translatable):
ctx.print(f"{name}: _(\"{_escape_quote(cdata)}\");")
ctx.print(f'{name}: _("{_escape_quote(cdata)}");')
else:
ctx.print_attribute(name, cdata, get_types(ctx.gir).get(name))
@decompiler("accessibility")
def decompile_accessibility(ctx, gir):
ctx.print("accessibility {")

View file

@ -35,12 +35,14 @@ class Item(BaseTypedAttribute):
item = Group(
Item,
[
Optional([
UseIdent("name"),
":",
]),
Optional(
[
UseIdent("name"),
":",
]
),
VALUE_HOOKS,
]
],
)
@ -67,7 +69,4 @@ class Items(AstNode):
matches=new_statement_patterns,
)
def items_completer(ast_node, match_variables):
yield Completion(
"items", CompletionItemKind.Snippet,
snippet="items [$0]"
)
yield Completion("items", CompletionItemKind.Snippet, snippet="items [$0]")

View file

@ -37,6 +37,7 @@ class Filters(AstNode):
f"Duplicate {self.tokens['tag_name']} block",
check=lambda child: child.tokens["tag_name"] == self.tokens["tag_name"],
)
wrapped_validator(self)
@ -57,12 +58,12 @@ def create_node(tag_name: str, singular: str):
[
UseQuoted("name"),
UseLiteral("tag_name", singular),
]
],
),
",",
),
"]",
]
],
)
@ -77,31 +78,38 @@ suffixes = create_node("suffixes", "suffix")
matches=new_statement_patterns,
)
def file_filter_completer(ast_node, match_variables):
yield Completion("mime-types", CompletionItemKind.Snippet, snippet="mime-types [\"$0\"]")
yield Completion("patterns", CompletionItemKind.Snippet, snippet="patterns [\"$0\"]")
yield Completion("suffixes", CompletionItemKind.Snippet, snippet="suffixes [\"$0\"]")
yield Completion(
"mime-types", CompletionItemKind.Snippet, snippet='mime-types ["$0"]'
)
yield Completion("patterns", CompletionItemKind.Snippet, snippet='patterns ["$0"]')
yield Completion("suffixes", CompletionItemKind.Snippet, snippet='suffixes ["$0"]')
@decompiler("mime-types")
def decompile_mime_types(ctx, gir):
ctx.print("mime-types [")
@decompiler("mime-type", cdata=True)
def decompile_mime_type(ctx, gir, cdata):
ctx.print(f'"{cdata}",')
@decompiler("patterns")
def decompile_patterns(ctx, gir):
ctx.print("patterns [")
@decompiler("pattern", cdata=True)
def decompile_pattern(ctx, gir, cdata):
ctx.print(f'"{cdata}",')
@decompiler("suffixes")
def decompile_suffixes(ctx, gir):
ctx.print("suffixes [")
@decompiler("suffix", cdata=True)
def decompile_suffix(ctx, gir, cdata):
ctx.print(f'"{cdata}",')

View file

@ -45,7 +45,7 @@ layout_prop = Group(
UseIdent("name"),
":",
VALUE_HOOKS.expected("a value"),
)
),
)
@ -71,10 +71,7 @@ class Layout(AstNode):
matches=new_statement_patterns,
)
def layout_completer(ast_node, match_variables):
yield Completion(
"layout", CompletionItemKind.Snippet,
snippet="layout {\n $0\n}"
)
yield Completion("layout", CompletionItemKind.Snippet, snippet="layout {\n $0\n}")
@decompiler("layout")

View file

@ -56,22 +56,12 @@ menu_contents = Sequence()
menu_section = Group(
Menu,
[
"section",
UseLiteral("tag", "section"),
Optional(UseIdent("id")),
menu_contents
]
["section", UseLiteral("tag", "section"), Optional(UseIdent("id")), menu_contents],
)
menu_submenu = Group(
Menu,
[
"submenu",
UseLiteral("tag", "submenu"),
Optional(UseIdent("id")),
menu_contents
]
["submenu", UseLiteral("tag", "submenu"), Optional(UseIdent("id")), menu_contents],
)
menu_attribute = Group(
@ -81,7 +71,7 @@ menu_attribute = Group(
":",
VALUE_HOOKS.expected("a value"),
Match(";").expected(),
]
],
)
menu_item = Group(
@ -92,7 +82,7 @@ menu_item = Group(
Optional(UseIdent("id")),
Match("{").expected(),
Until(menu_attribute, "}"),
]
],
)
menu_item_shorthand = Group(
@ -105,58 +95,60 @@ menu_item_shorthand = Group(
MenuAttribute,
[UseLiteral("name", "label"), VALUE_HOOKS],
),
Optional([
",",
Optional([
Group(
MenuAttribute,
[UseLiteral("name", "action"), VALUE_HOOKS],
Optional(
[
",",
Optional(
[
Group(
MenuAttribute,
[UseLiteral("name", "action"), VALUE_HOOKS],
),
Optional(
[
",",
Group(
MenuAttribute,
[UseLiteral("name", "icon"), VALUE_HOOKS],
),
]
),
]
),
Optional([
",",
Group(
MenuAttribute,
[UseLiteral("name", "icon"), VALUE_HOOKS],
),
])
])
]),
]
),
Match(")").expected(),
]
],
)
menu_contents.children = [
Match("{"),
Until(AnyOf(
menu_section,
menu_submenu,
menu_item_shorthand,
menu_item,
menu_attribute,
), "}"),
Until(
AnyOf(
menu_section,
menu_submenu,
menu_item_shorthand,
menu_item,
menu_attribute,
),
"}",
),
]
menu: Group = Group(
Menu,
[
"menu",
UseLiteral("tag", "menu"),
Optional(UseIdent("id")),
menu_contents
],
["menu", UseLiteral("tag", "menu"), Optional(UseIdent("id")), menu_contents],
)
from .ui import UI
@completer(
applies_in=[UI],
matches=new_statement_patterns,
)
def menu_completer(ast_node, match_variables):
yield Completion(
"menu", CompletionItemKind.Snippet,
snippet="menu {\n $0\n}"
)
yield Completion("menu", CompletionItemKind.Snippet, snippet="menu {\n $0\n}")
@completer(
@ -165,34 +157,21 @@ def menu_completer(ast_node, match_variables):
)
def menu_content_completer(ast_node, match_variables):
yield Completion(
"submenu", CompletionItemKind.Snippet,
snippet="submenu {\n $0\n}"
"submenu", CompletionItemKind.Snippet, snippet="submenu {\n $0\n}"
)
yield Completion(
"section", CompletionItemKind.Snippet,
snippet="section {\n $0\n}"
"section", CompletionItemKind.Snippet, snippet="section {\n $0\n}"
)
yield Completion("item", CompletionItemKind.Snippet, snippet="item {\n $0\n}")
yield Completion(
"item", CompletionItemKind.Snippet,
snippet="item {\n $0\n}"
)
yield Completion(
"item (shorthand)", CompletionItemKind.Snippet,
snippet='item (_("${1:Label}"), "${2:action-name}", "${3:icon-name}")'
"item (shorthand)",
CompletionItemKind.Snippet,
snippet='item (_("${1:Label}"), "${2:action-name}", "${3:icon-name}")',
)
yield Completion(
"label", CompletionItemKind.Snippet,
snippet='label: $0;'
)
yield Completion(
"action", CompletionItemKind.Snippet,
snippet='action: "$0";'
)
yield Completion(
"icon", CompletionItemKind.Snippet,
snippet='icon: "$0";'
)
yield Completion("label", CompletionItemKind.Snippet, snippet="label: $0;")
yield Completion("action", CompletionItemKind.Snippet, snippet='action: "$0";')
yield Completion("icon", CompletionItemKind.Snippet, snippet='icon: "$0";')
@decompiler("menu")
@ -202,6 +181,7 @@ def decompile_menu(ctx, gir, id=None):
else:
ctx.print("menu {")
@decompiler("submenu")
def decompile_submenu(ctx, gir, id=None):
if id:
@ -209,6 +189,7 @@ def decompile_submenu(ctx, gir, id=None):
else:
ctx.print("submenu {")
@decompiler("item")
def decompile_item(ctx, gir, id=None):
if id:
@ -216,6 +197,7 @@ def decompile_item(ctx, gir, id=None):
else:
ctx.print("item {")
@decompiler("section")
def decompile_section(ctx, gir, id=None):
if id:

View file

@ -32,7 +32,7 @@ class Widget(AstNode):
if object is None:
raise CompileError(
f"Could not find object with ID {self.tokens['name']}",
did_you_mean=(self.tokens['name'], self.root.objects_by_id.keys()),
did_you_mean=(self.tokens["name"], self.root.objects_by_id.keys()),
)
elif object.gir_class and not object.gir_class.assignable_to(type):
raise CompileError(

View file

@ -55,7 +55,4 @@ class Strings(AstNode):
matches=new_statement_patterns,
)
def strings_completer(ast_node, match_variables):
yield Completion(
"strings", CompletionItemKind.Snippet,
snippet="strings [$0]"
)
yield Completion("strings", CompletionItemKind.Snippet, snippet="strings [$0]")

View file

@ -49,13 +49,14 @@ class Styles(AstNode):
matches=new_statement_patterns,
)
def style_completer(ast_node, match_variables):
yield Completion("styles", CompletionItemKind.Keyword, snippet="styles [\"$0\"]")
yield Completion("styles", CompletionItemKind.Keyword, snippet='styles ["$0"]')
@decompiler("style")
def decompile_style(ctx, gir):
ctx.print(f"styles [")
@decompiler("class")
def decompile_style_class(ctx, gir, name):
ctx.print(f'"{name}",')

View file

@ -26,18 +26,21 @@ from .common import *
ALLOWED_PARENTS: T.List[T.Tuple[str, str]] = [
("Gtk", "Buildable"),
("Gio", "ListStore")
("Gio", "ListStore"),
]
class Child(AstNode):
grammar = [
Optional([
"[",
Optional(["internal-child", UseLiteral("internal_child", True)]),
UseIdent("child_type").expected("a child type"),
Optional(ResponseId),
"]",
]),
Optional(
[
"[",
Optional(["internal-child", UseLiteral("internal_child", True)]),
UseIdent("child_type").expected("a child type"),
Optional(ResponseId),
"]",
]
),
Object,
]
@ -53,9 +56,13 @@ class Child(AstNode):
if gir_class.assignable_to(parent_type):
break
else:
hints=["only Gio.ListStore or Gtk.Buildable implementors can have children"]
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?")
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,

View file

@ -28,10 +28,12 @@ class Template(Object):
grammar = [
"template",
UseIdent("id").expected("template class name"),
Optional([
Match(":"),
to_parse_node(ClassName).expected("parent class"),
]),
Optional(
[
Match(":"),
to_parse_node(ClassName).expected("parent class"),
]
),
ObjectContent,
]
@ -54,7 +56,9 @@ class Template(Object):
@validate("id")
def unique_in_parent(self):
self.validate_unique_in_parent(f"Only one template may be defined per file, but this file contains {len(self.parent.children[Template])}",)
self.validate_unique_in_parent(
f"Only one template may be defined per file, but this file contains {len(self.parent.children[Template])}",
)
@decompiler("template")

View file

@ -24,8 +24,12 @@ from .common import *
class GtkDirective(AstNode):
grammar = Statement(
Match("using").err("File must start with a \"using Gtk\" directive (e.g. `using Gtk 4.0;`)"),
Match("Gtk").err("File must start with a \"using Gtk\" directive (e.g. `using Gtk 4.0;`)"),
Match("using").err(
'File must start with a "using Gtk" directive (e.g. `using Gtk 4.0;`)'
),
Match("Gtk").err(
'File must start with a "using Gtk" directive (e.g. `using Gtk 4.0;`)'
),
UseNumberText("version").expected("a version number for GTK"),
)
@ -35,7 +39,9 @@ class GtkDirective(AstNode):
if version not in ["4.0"]:
err = CompileError("Only GTK 4 is supported")
if version and version.startswith("4"):
err.hint("Expected the GIR version, not an exact version number. Use 'using Gtk 4.0;'.")
err.hint(
"Expected the GIR version, not an exact version number. Use 'using Gtk 4.0;'."
)
else:
err.hint("Expected 'using Gtk 4.0;'")
raise err
@ -51,7 +57,6 @@ class GtkDirective(AstNode):
hints=e.hints,
)
@property
def gir_namespace(self):
# validate the GTK version first to make sure the more specific error

View file

@ -26,21 +26,13 @@ from .common import *
class ResponseId(AstNode):
"""Response ID of action widget."""
ALLOWED_PARENTS: T.List[T.Tuple[str, str]] = [
("Gtk", "Dialog"),
("Gtk", "InfoBar")
]
ALLOWED_PARENTS: T.List[T.Tuple[str, str]] = [("Gtk", "Dialog"), ("Gtk", "InfoBar")]
grammar = [
Keyword("response"),
"=",
AnyOf(
UseIdent("response_id"),
UseNumber("response_id")
),
Optional([
Keyword("default"), UseLiteral("is_default", True)
])
AnyOf(UseIdent("response_id"), UseNumber("response_id")),
Optional([Keyword("default"), UseLiteral("is_default", True)]),
]
@validate()
@ -91,18 +83,15 @@ class ResponseId(AstNode):
if isinstance(response, int):
if response < 0:
raise CompileError(
"Numeric response type can't be negative")
raise CompileError("Numeric response type can't be negative")
elif isinstance(response, float):
raise CompileError(
"Response type must be GtkResponseType member or integer,"
" not float"
"Response type must be GtkResponseType member or integer," " not float"
)
else:
responses = gir.get_type("ResponseType", "Gtk").members.keys()
if response not in responses:
raise CompileError(
f"Response type \"{response}\" doesn't exist")
raise CompileError(f'Response type "{response}" doesn\'t exist')
@validate("default")
def no_multiple_default(self) -> None:
@ -135,4 +124,3 @@ class ResponseId(AstNode):
_object: Object = self.parent.children[Object][0]
return _object.tokens["id"]

View file

@ -41,7 +41,9 @@ class TypeName(AstNode):
@validate("class_name")
def type_exists(self):
if not self.tokens["ignore_gir"] and self.gir_ns is not None:
self.root.gir.validate_type(self.tokens["class_name"], self.tokens["namespace"])
self.root.gir.validate_type(
self.tokens["class_name"], self.tokens["namespace"]
)
@validate("namespace")
def gir_ns_exists(self):
@ -56,7 +58,9 @@ class TypeName(AstNode):
@property
def gir_type(self) -> T.Optional[gir.Class]:
if self.tokens["class_name"] and not self.tokens["ignore_gir"]:
return self.root.gir.get_type(self.tokens["class_name"], self.tokens["namespace"])
return self.root.gir.get_type(
self.tokens["class_name"], self.tokens["namespace"]
)
return None
@property
@ -82,7 +86,9 @@ class ClassName(TypeName):
def gir_class_exists(self):
if self.gir_type is not None and not isinstance(self.gir_type, Class):
if isinstance(self.gir_type, Interface):
raise CompileError(f"{self.gir_type.full_name} is an interface, not a class")
raise CompileError(
f"{self.gir_type.full_name} is an interface, not a class"
)
else:
raise CompileError(f"{self.gir_type.full_name} is not a class")
@ -93,6 +99,5 @@ class ConcreteClassName(ClassName):
if isinstance(self.gir_type, Class) and self.gir_type.abstract:
raise CompileError(
f"{self.gir_type.full_name} can't be instantiated because it's abstract",
hints=[f"did you mean to use a subclass of {self.gir_type.full_name}?"]
hints=[f"did you mean to use a subclass of {self.gir_type.full_name}?"],
)

View file

@ -27,16 +27,19 @@ from .common import *
class UI(AstNode):
""" The AST node for the entire file """
"""The AST node for the entire file"""
grammar = [
GtkDirective,
ZeroOrMore(Import),
Until(AnyOf(
Template,
menu,
Object,
), Eof()),
Until(
AnyOf(
Template,
menu,
Object,
),
Eof(),
),
]
@property
@ -61,11 +64,13 @@ class UI(AstNode):
return gir_ctx
@property
def objects_by_id(self):
return { obj.tokens["id"]: obj for obj in self.iterate_children_recursive() if obj.tokens["id"] is not None }
return {
obj.tokens["id"]: obj
for obj in self.iterate_children_recursive()
if obj.tokens["id"] is not None
}
@validate()
def gir_errors(self):
@ -74,7 +79,6 @@ class UI(AstNode):
if len(self._gir_errors):
raise MultipleErrors(self._gir_errors)
@validate()
def unique_ids(self):
passed = {}
@ -84,5 +88,7 @@ class UI(AstNode):
if obj.tokens["id"] in passed:
token = obj.group.tokens["id"]
raise CompileError(f"Duplicate object ID '{obj.tokens['id']}'", token.start, token.end)
raise CompileError(
f"Duplicate object ID '{obj.tokens['id']}'", token.start, token.end
)
passed[obj.tokens["id"]] = obj

View file

@ -84,13 +84,21 @@ class QuotedValue(Value):
@validate()
def validate_for_type(self):
type = self.parent.value_type
if isinstance(type, gir.IntType) or isinstance(type, gir.UIntType) or isinstance(type, gir.FloatType):
if (
isinstance(type, gir.IntType)
or isinstance(type, gir.UIntType)
or isinstance(type, gir.FloatType)
):
raise CompileError(f"Cannot convert string to number")
elif isinstance(type, gir.StringType):
pass
elif isinstance(type, gir.Class) or isinstance(type, gir.Interface) or isinstance(type, gir.Boxed):
elif (
isinstance(type, gir.Class)
or isinstance(type, gir.Interface)
or isinstance(type, gir.Boxed)
):
parseable_types = [
"Gdk.Paintable",
"Gdk.Texture",
@ -106,8 +114,12 @@ class QuotedValue(Value):
if type.full_name not in parseable_types:
hints = []
if isinstance(type, gir.TypeType):
hints.append(f"use the typeof operator: 'typeof({self.tokens('value')})'")
raise CompileError(f"Cannot convert string to {type.full_name}", hints=hints)
hints.append(
f"use the typeof operator: 'typeof({self.tokens('value')})'"
)
raise CompileError(
f"Cannot convert string to {type.full_name}", hints=hints
)
elif type is not None:
raise CompileError(f"Cannot convert string to {type.full_name}")
@ -127,7 +139,9 @@ class NumberValue(Value):
try:
int(self.tokens["value"])
except:
raise CompileError(f"Cannot convert {self.group.tokens['value']} to integer")
raise CompileError(
f"Cannot convert {self.group.tokens['value']} to integer"
)
elif isinstance(type, gir.UIntType):
try:
@ -135,13 +149,17 @@ class NumberValue(Value):
if int(self.tokens["value"]) < 0:
raise Exception()
except:
raise CompileError(f"Cannot convert {self.group.tokens['value']} to unsigned integer")
raise CompileError(
f"Cannot convert {self.group.tokens['value']} to unsigned integer"
)
elif isinstance(type, gir.FloatType):
try:
float(self.tokens["value"])
except:
raise CompileError(f"Cannot convert {self.group.tokens['value']} to float")
raise CompileError(
f"Cannot convert {self.group.tokens['value']} to float"
)
elif type is not None:
raise CompileError(f"Cannot convert number to {type.full_name}")
@ -164,7 +182,7 @@ class Flag(AstNode):
if isinstance(type, gir.Bitfield) and self.tokens["value"] not in type.members:
raise CompileError(
f"{self.tokens['value']} is not a member of {type.full_name}",
did_you_mean=(self.tokens['value'], type.members.keys()),
did_you_mean=(self.tokens["value"], type.members.keys()),
)
@ -189,14 +207,14 @@ class IdentValue(Value):
if self.tokens["value"] not in type.members:
raise CompileError(
f"{self.tokens['value']} is not a member of {type.full_name}",
did_you_mean=(self.tokens['value'], type.members.keys()),
did_you_mean=(self.tokens["value"], type.members.keys()),
)
elif isinstance(type, gir.BoolType):
if self.tokens["value"] not in ["true", "false"]:
raise CompileError(
f"Expected 'true' or 'false' for boolean value",
did_you_mean=(self.tokens['value'], ["true", "false"]),
did_you_mean=(self.tokens["value"], ["true", "false"]),
)
elif type is not None:
@ -204,14 +222,13 @@ class IdentValue(Value):
if object is None:
raise CompileError(
f"Could not find object with ID {self.tokens['value']}",
did_you_mean=(self.tokens['value'], self.root.objects_by_id.keys()),
did_you_mean=(self.tokens["value"], self.root.objects_by_id.keys()),
)
elif object.gir_class and not object.gir_class.assignable_to(type):
raise CompileError(
f"Cannot assign {object.gir_class.full_name} to {type.full_name}"
)
@docs()
def docs(self):
type = self.parent.value_type
@ -223,9 +240,7 @@ class IdentValue(Value):
elif isinstance(type, gir.GirNode):
return type.doc
def get_semantic_tokens(self) -> T.Iterator[SemanticToken]:
if isinstance(self.parent.value_type, gir.Enumeration):
token = self.group.tokens["value"]
yield SemanticToken(token.start, token.end, SemanticTokenType.EnumMember)