mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
tests: Test custom types in lookup expressions
This commit is contained in:
parent
76a482affb
commit
cd33266452
11 changed files with 93 additions and 7 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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"],
|
||||
})
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -1,3 +1,5 @@
|
|||
using Gtk 4.0;
|
||||
|
||||
template TestTemplate : Gtk.Orientable {}
|
||||
Gtk.Orientable {}
|
||||
int {}
|
||||
|
|
|
@ -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
|
8
tests/samples/expr_custom_types.blp
Normal file
8
tests/samples/expr_custom_types.blp
Normal file
|
@ -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;
|
||||
}
|
17
tests/samples/expr_custom_types.ui
Normal file
17
tests/samples/expr_custom_types.ui
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="MyWidget" id="widget"></object>
|
||||
<object class="MyOtherWidget" id="other_widget">
|
||||
<binding name="property">
|
||||
<lookup name="other" type="MyObject">
|
||||
<lookup name="something" type="MyWidget">
|
||||
<constant>widget</constant>
|
||||
</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<property name="expr-prop">
|
||||
<lookup name="other" type="MyObject"/>
|
||||
</property>
|
||||
</object>
|
||||
</interface>
|
|
@ -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")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue