From cd33266452257fa272aae5de08cd357d8ef63058 Mon Sep 17 00:00:00 2001 From: James Westman Date: Sat, 30 Apr 2022 16:13:40 -0500 Subject: [PATCH] tests: Test custom types in lookup expressions --- blueprintcompiler/language/common.py | 10 ++++++- blueprintcompiler/language/expression.py | 30 ++++++++++++++++++-- blueprintcompiler/language/gobject_object.py | 23 +++++++++++++-- blueprintcompiler/language/lambdas.py | 3 ++ blueprintcompiler/language/ui.py | 2 +- tests/sample_errors/abstract_class.err | 2 +- tests/sample_errors/not_a_class.blp | 2 ++ tests/sample_errors/not_a_class.err | 2 ++ tests/samples/expr_custom_types.blp | 8 ++++++ tests/samples/expr_custom_types.ui | 17 +++++++++++ tests/test_samples.py | 1 + 11 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 tests/samples/expr_custom_types.blp create mode 100644 tests/samples/expr_custom_types.ui diff --git a/blueprintcompiler/language/common.py b/blueprintcompiler/language/common.py index 7f524c2..8996f68 100644 --- a/blueprintcompiler/language/common.py +++ b/blueprintcompiler/language/common.py @@ -36,10 +36,11 @@ VALUE_HOOKS = AnyOf() class ScopeVariable: - def __init__(self, name: str, gir_class: gir.GirType, xml_func): + def __init__(self, name: str, gir_class: gir.GirType, xml_func, glib_type_name=None): self._name = name self._gir_class = gir_class self._xml_func = xml_func + self._glib_type_name = glib_type_name @property def name(self) -> str: @@ -49,6 +50,13 @@ class ScopeVariable: def gir_class(self) -> gir.GirType: return self._gir_class + @property + def glib_type_name(self) -> str: + if self._glib_type_name is not None: + return self._glib_type_name + elif self.gir_class: + return self.gir_class.glib_type_name + def emit_xml(self, xml: XmlEmitter): if f := self._xml_func: f(xml) diff --git a/blueprintcompiler/language/expression.py b/blueprintcompiler/language/expression.py index 81477cc..b4bcde1 100644 --- a/blueprintcompiler/language/expression.py +++ b/blueprintcompiler/language/expression.py @@ -32,6 +32,10 @@ class Expr(AstNode): def gir_type(self): return self.children[-1].gir_type + @property + def glib_type_name(self): + return self.children[-1].glib_type_name + def emit_xml(self, xml: XmlEmitter): self.children[-1].emit_xml(xml) @@ -71,6 +75,15 @@ class IdentExpr(AstNode): elif self.tokens["ident"] in scope.variables: return scope.variables[self.tokens["ident"]].gir_class + @property + def glib_type_name(self): + scope = self.parent_by_type(Scope) + + if self.is_this: + return scope.this_type_glib_name + elif self.tokens["ident"] in scope.variables: + return scope.variables[self.tokens["ident"]].glib_type_name + def emit_xml(self, xml: XmlEmitter): if self.is_this: raise CompilerBugError() @@ -95,6 +108,10 @@ class ClosureExpr(AstNode): def gir_type(self): return self.parent.parent.gir_type + @property + def glib_type_name(self): + return self.parent.parent.glib_type_name + def emit_xml(self, xml: XmlEmitter): xml.start_tag("closure", function=self.tokens["function"], type=self.gir_type) for child in self.children[Expr]: @@ -111,6 +128,11 @@ class LookupOp(InfixExpr): if prop := parent_type.properties.get(self.tokens["property"]): return prop.type + @property + def glib_type_name(self): + if self.gir_type is not None: + return self.gir_type.glib_type_name + @validate("property") def property_exists(self): if parent_type := self.lhs.gir_type: @@ -125,9 +147,9 @@ class LookupOp(InfixExpr): def emit_xml(self, xml: XmlEmitter): if isinstance(self.lhs, IdentExpr) and self.lhs.is_this: - xml.put_self_closing("lookup", name=self.tokens["property"], type=self.parent_by_type(Scope).this_type) + xml.put_self_closing("lookup", name=self.tokens["property"], type=self.parent_by_type(Scope).this_type_glib_name) else: - xml.start_tag("lookup", name=self.tokens["property"], type=self.lhs.gir_type) + xml.start_tag("lookup", name=self.tokens["property"], type=self.lhs.glib_type_name) self.lhs.emit_xml(xml) xml.end_tag() @@ -139,6 +161,10 @@ class CastExpr(AstNode): def gir_type(self): return self.children[TypeName][0].gir_type + @property + def glib_type_name(self): + return self.children[TypeName][0].glib_type_name + def emit_xml(self, xml: XmlEmitter): self.children[Expr][0].emit_xml(xml) diff --git a/blueprintcompiler/language/gobject_object.py b/blueprintcompiler/language/gobject_object.py index 9a78667..4a3c2ef 100644 --- a/blueprintcompiler/language/gobject_object.py +++ b/blueprintcompiler/language/gobject_object.py @@ -21,6 +21,8 @@ import typing as T from functools import cached_property +from ..gir import Class +from .types import ConcreteClassName, ClassName from .common import * from .response_id import ResponseId from .types import ClassName, ConcreteClassName @@ -46,7 +48,24 @@ class Object(AstNode): @property def gir_class(self): - return self.children[ClassName][0].gir_type + class_names = self.children[ClassName] + if len(class_names) > 0: + if isinstance(class_names[0].gir_type, Class): + return class_names[0].gir_type + + @property + def glib_type_name(self) -> str: + return self.children[ClassName][0].glib_type_name + + @docs("namespace") + def namespace_docs(self): + if ns := self.root.gir.namespaces.get(self.tokens["namespace"]): + return ns.doc + + @docs("class_name") + def class_docs(self): + if self.gir_class: + return self.gir_class.doc @cached_property def action_widgets(self) -> T.List[ResponseId]: @@ -64,7 +83,7 @@ class Object(AstNode): def emit_start_tag(self, xml: XmlEmitter): xml.start_tag("object", **{ - "class": self.children[ClassName][0].glib_type_name, + "class": self.glib_type_name, "id": self.tokens["id"], }) diff --git a/blueprintcompiler/language/lambdas.py b/blueprintcompiler/language/lambdas.py index 25dfd73..59a66ff 100644 --- a/blueprintcompiler/language/lambdas.py +++ b/blueprintcompiler/language/lambdas.py @@ -53,3 +53,6 @@ class Lambda(Value, Scope): def this_type(self) -> str: return self.children[TypeName][0].gir_type + @property + def this_type_glib_name(self) -> str: + return self.children[TypeName][0].glib_type_name diff --git a/blueprintcompiler/language/ui.py b/blueprintcompiler/language/ui.py index 541fd24..b20e739 100644 --- a/blueprintcompiler/language/ui.py +++ b/blueprintcompiler/language/ui.py @@ -70,7 +70,7 @@ class UI(AstNode, Scope): xml.end_tag() return { - id: ScopeVariable(id, obj.gir_class, lambda xml: emit_xml(xml, id)) + id: ScopeVariable(id, obj.gir_class, lambda xml, id=id: emit_xml(xml, id), obj.glib_type_name) for id, obj in self.objects_by_id.items() } diff --git a/tests/sample_errors/abstract_class.err b/tests/sample_errors/abstract_class.err index 1765fc4..f682ead 100644 --- a/tests/sample_errors/abstract_class.err +++ b/tests/sample_errors/abstract_class.err @@ -1 +1 @@ -4,1,10,Gtk.Widget can't be instantiated because it's abstract +4,1,10,Gtk.Widget can't be instantiated because it's abstract \ No newline at end of file diff --git a/tests/sample_errors/not_a_class.blp b/tests/sample_errors/not_a_class.blp index 0383154..bdc510b 100644 --- a/tests/sample_errors/not_a_class.blp +++ b/tests/sample_errors/not_a_class.blp @@ -1,3 +1,5 @@ using Gtk 4.0; template TestTemplate : Gtk.Orientable {} +Gtk.Orientable {} +int {} diff --git a/tests/sample_errors/not_a_class.err b/tests/sample_errors/not_a_class.err index c69f602..a181722 100644 --- a/tests/sample_errors/not_a_class.err +++ b/tests/sample_errors/not_a_class.err @@ -1 +1,3 @@ 3,25,14,Gtk.Orientable is an interface, not a class +4,1,14,Gtk.Orientable is an interface, not a class +5,1,3,int is not a class \ No newline at end of file diff --git a/tests/samples/expr_custom_types.blp b/tests/samples/expr_custom_types.blp new file mode 100644 index 0000000..308977a --- /dev/null +++ b/tests/samples/expr_custom_types.blp @@ -0,0 +1,8 @@ +using Gtk 4.0; + +.MyWidget widget {} + +.MyOtherWidget other_widget { + property: bind ((.MyObject) widget.something).other; + expr-prop: (.MyObject obj) => obj.other; +} diff --git a/tests/samples/expr_custom_types.ui b/tests/samples/expr_custom_types.ui new file mode 100644 index 0000000..0407fda --- /dev/null +++ b/tests/samples/expr_custom_types.ui @@ -0,0 +1,17 @@ + + + + + + + + + widget + + + + + + + + diff --git a/tests/test_samples.py b/tests/test_samples.py index e581cb8..80937fb 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -137,6 +137,7 @@ class TestSamples(unittest.TestCase): self.assert_sample("comments") self.assert_sample("enum") self.assert_sample("expr_closure") + self.assert_sample("expr_custom_types") self.assert_sample("expr_lookup") self.assert_sample("file_filter") self.assert_sample("flags")