mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-07 16:29:07 -04:00
Compare commits
2 commits
a20d21f8fb
...
76ed182163
Author | SHA1 | Date | |
---|---|---|---|
|
76ed182163 | ||
|
ffb125a725 |
23 changed files with 54 additions and 57 deletions
|
@ -41,7 +41,7 @@ from .types import ClassName
|
||||||
from .ui import UI
|
from .ui import UI
|
||||||
from .values import (
|
from .values import (
|
||||||
ArrayValue,
|
ArrayValue,
|
||||||
ExprValue,
|
ExprLiteral,
|
||||||
Flag,
|
Flag,
|
||||||
Flags,
|
Flags,
|
||||||
IdentLiteral,
|
IdentLiteral,
|
||||||
|
|
|
@ -82,6 +82,6 @@ class ScopeCtx:
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ExprValueCtx:
|
class ExprLiteralCtx:
|
||||||
"""Indicates that the context is an expression literal, where the
|
"""Indicates that the context is an expression literal, where the
|
||||||
"item" keyword may be used."""
|
"item" keyword may be used."""
|
||||||
|
|
|
@ -21,12 +21,13 @@
|
||||||
from .binding import Binding
|
from .binding import Binding
|
||||||
from .common import *
|
from .common import *
|
||||||
from .contexts import ValueTypeCtx
|
from .contexts import ValueTypeCtx
|
||||||
from .values import ArrayValue, ExprValue, ObjectValue, Value
|
from .gtkbuilder_template import Template
|
||||||
|
from .values import ArrayValue, ObjectValue, Value
|
||||||
|
|
||||||
|
|
||||||
class Property(AstNode):
|
class Property(AstNode):
|
||||||
grammar = Statement(
|
grammar = Statement(
|
||||||
UseIdent("name"), ":", AnyOf(Binding, ExprValue, ObjectValue, Value, ArrayValue)
|
UseIdent("name"), ":", AnyOf(Binding, ObjectValue, Value, ArrayValue)
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -34,7 +35,7 @@ class Property(AstNode):
|
||||||
return self.tokens["name"]
|
return self.tokens["name"]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> T.Union[Binding, ExprValue, ObjectValue, Value, ArrayValue]:
|
def value(self) -> T.Union[Binding, ObjectValue, Value, ArrayValue]:
|
||||||
return self.children[0]
|
return self.children[0]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -143,13 +143,12 @@ class Signal(AstNode):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def document_symbol(self) -> DocumentSymbol:
|
def document_symbol(self) -> DocumentSymbol:
|
||||||
detail = self.ranges["detail_start", "detail_end"]
|
|
||||||
return DocumentSymbol(
|
return DocumentSymbol(
|
||||||
self.full_name,
|
self.full_name,
|
||||||
SymbolKind.Event,
|
SymbolKind.Event,
|
||||||
self.range,
|
self.range,
|
||||||
self.group.tokens["name"].range,
|
self.group.tokens["name"].range,
|
||||||
detail.text if detail is not None else None,
|
self.ranges["detail_start", "detail_end"].text,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_reference(self, idx: int) -> T.Optional[LocationLink]:
|
def get_reference(self, idx: int) -> T.Optional[LocationLink]:
|
||||||
|
|
|
@ -23,7 +23,7 @@ from blueprintcompiler.gir import ArrayType
|
||||||
from blueprintcompiler.lsp_utils import SemanticToken
|
from blueprintcompiler.lsp_utils import SemanticToken
|
||||||
|
|
||||||
from .common import *
|
from .common import *
|
||||||
from .contexts import ExprValueCtx, ScopeCtx, ValueTypeCtx
|
from .contexts import ExprLiteralCtx, ScopeCtx, ValueTypeCtx
|
||||||
from .expression import Expression
|
from .expression import Expression
|
||||||
from .gobject_object import Object
|
from .gobject_object import Object
|
||||||
from .types import TypeName
|
from .types import TypeName
|
||||||
|
@ -112,6 +112,35 @@ class TypeLiteral(AstNode):
|
||||||
return get_docs_section("Syntax TypeLiteral")
|
return get_docs_section("Syntax TypeLiteral")
|
||||||
|
|
||||||
|
|
||||||
|
class ExprLiteral(AstNode):
|
||||||
|
grammar = [Keyword("expr"), Expression]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def expression(self) -> Expression:
|
||||||
|
return self.children[Expression][0]
|
||||||
|
|
||||||
|
@validate("expr")
|
||||||
|
def validate_for_type(self) -> None:
|
||||||
|
expected_type = self.parent.context[ValueTypeCtx].value_type
|
||||||
|
expr_type = self.root.gir.get_type("Expression", "Gtk")
|
||||||
|
if expected_type is not None and not expected_type.assignable_to(expr_type):
|
||||||
|
raise CompileError(
|
||||||
|
f"Cannot convert Gtk.Expression to {expected_type.full_name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
@docs("expr")
|
||||||
|
def ref_docs(self):
|
||||||
|
return get_docs_section("Syntax ExprLiteral")
|
||||||
|
|
||||||
|
@context(ExprLiteralCtx)
|
||||||
|
def expr_literal(self):
|
||||||
|
return ExprLiteralCtx()
|
||||||
|
|
||||||
|
@context(ValueTypeCtx)
|
||||||
|
def value_type(self):
|
||||||
|
return ValueTypeCtx(None, must_infer_type=True)
|
||||||
|
|
||||||
|
|
||||||
class QuotedLiteral(AstNode):
|
class QuotedLiteral(AstNode):
|
||||||
grammar = UseQuoted("value")
|
grammar = UseQuoted("value")
|
||||||
|
|
||||||
|
@ -321,7 +350,7 @@ class IdentLiteral(AstNode):
|
||||||
if not self.context[ValueTypeCtx].allow_null:
|
if not self.context[ValueTypeCtx].allow_null:
|
||||||
raise CompileError("null is not permitted here")
|
raise CompileError("null is not permitted here")
|
||||||
elif self.ident == "item":
|
elif self.ident == "item":
|
||||||
if not self.context[ExprValueCtx]:
|
if not self.context[ExprLiteralCtx]:
|
||||||
raise CompileError(
|
raise CompileError(
|
||||||
'"item" can only be used in an expression literal'
|
'"item" can only be used in an expression literal'
|
||||||
)
|
)
|
||||||
|
@ -381,6 +410,7 @@ class IdentLiteral(AstNode):
|
||||||
class Literal(AstNode):
|
class Literal(AstNode):
|
||||||
grammar = AnyOf(
|
grammar = AnyOf(
|
||||||
TypeLiteral,
|
TypeLiteral,
|
||||||
|
ExprLiteral,
|
||||||
QuotedLiteral,
|
QuotedLiteral,
|
||||||
NumberLiteral,
|
NumberLiteral,
|
||||||
IdentLiteral,
|
IdentLiteral,
|
||||||
|
@ -389,7 +419,7 @@ class Literal(AstNode):
|
||||||
@property
|
@property
|
||||||
def value(
|
def value(
|
||||||
self,
|
self,
|
||||||
) -> T.Union[TypeLiteral, QuotedLiteral, NumberLiteral, IdentLiteral]:
|
) -> T.Union[TypeLiteral, ExprLiteral, QuotedLiteral, NumberLiteral, IdentLiteral]:
|
||||||
return self.children[0]
|
return self.children[0]
|
||||||
|
|
||||||
|
|
||||||
|
@ -413,35 +443,6 @@ class ObjectValue(AstNode):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ExprValue(AstNode):
|
|
||||||
grammar = [Keyword("expr"), Expression]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def expression(self) -> Expression:
|
|
||||||
return self.children[Expression][0]
|
|
||||||
|
|
||||||
@validate("expr")
|
|
||||||
def validate_for_type(self) -> None:
|
|
||||||
expected_type = self.parent.context[ValueTypeCtx].value_type
|
|
||||||
expr_type = self.root.gir.get_type("Expression", "Gtk")
|
|
||||||
if expected_type is not None and not expected_type.assignable_to(expr_type):
|
|
||||||
raise CompileError(
|
|
||||||
f"Cannot convert Gtk.Expression to {expected_type.full_name}"
|
|
||||||
)
|
|
||||||
|
|
||||||
@docs("expr")
|
|
||||||
def ref_docs(self):
|
|
||||||
return get_docs_section("Syntax ExprValue")
|
|
||||||
|
|
||||||
@context(ExprValueCtx)
|
|
||||||
def expr_literal(self):
|
|
||||||
return ExprValueCtx()
|
|
||||||
|
|
||||||
@context(ValueTypeCtx)
|
|
||||||
def value_type(self):
|
|
||||||
return ValueTypeCtx(None, must_infer_type=True)
|
|
||||||
|
|
||||||
|
|
||||||
class Value(AstNode):
|
class Value(AstNode):
|
||||||
grammar = AnyOf(Translated, Flags, Literal)
|
grammar = AnyOf(Translated, Flags, Literal)
|
||||||
|
|
||||||
|
|
|
@ -134,11 +134,6 @@ class XmlOutput(OutputFormat):
|
||||||
self._emit_expression(value.expression, xml)
|
self._emit_expression(value.expression, xml)
|
||||||
xml.end_tag()
|
xml.end_tag()
|
||||||
|
|
||||||
elif isinstance(value, ExprValue):
|
|
||||||
xml.start_tag("property", **props)
|
|
||||||
self._emit_expression(value.expression, xml)
|
|
||||||
xml.end_tag()
|
|
||||||
|
|
||||||
elif isinstance(value, ObjectValue):
|
elif isinstance(value, ObjectValue):
|
||||||
xml.start_tag("property", **props)
|
xml.start_tag("property", **props)
|
||||||
self._emit_object(value.object, xml)
|
self._emit_object(value.object, xml)
|
||||||
|
@ -210,6 +205,8 @@ class XmlOutput(OutputFormat):
|
||||||
xml.put_text(self._object_id(value, value.ident))
|
xml.put_text(self._object_id(value, value.ident))
|
||||||
elif isinstance(value, TypeLiteral):
|
elif isinstance(value, TypeLiteral):
|
||||||
xml.put_text(value.type_name.glib_type_name)
|
xml.put_text(value.type_name.glib_type_name)
|
||||||
|
elif isinstance(value, ExprLiteral):
|
||||||
|
self._emit_expression(value.expression, xml)
|
||||||
else:
|
else:
|
||||||
if isinstance(value.value, float) and value.value == int(value.value):
|
if isinstance(value.value, float) and value.value == int(value.value):
|
||||||
xml.put_text(int(value.value))
|
xml.put_text(int(value.value))
|
||||||
|
@ -223,6 +220,12 @@ class XmlOutput(OutputFormat):
|
||||||
xml.put_text(
|
xml.put_text(
|
||||||
"|".join([str(flag.value or flag.name) for flag in value.child.flags])
|
"|".join([str(flag.value or flag.name) for flag in value.child.flags])
|
||||||
)
|
)
|
||||||
|
elif isinstance(value.child, Translated):
|
||||||
|
raise CompilerBugError("translated values must be handled in the parent")
|
||||||
|
elif isinstance(value.child, TypeLiteral):
|
||||||
|
xml.put_text(value.child.type_name.glib_type_name)
|
||||||
|
elif isinstance(value.child, ObjectValue):
|
||||||
|
self._emit_object(value.child.object, xml)
|
||||||
else:
|
else:
|
||||||
raise CompilerBugError()
|
raise CompilerBugError()
|
||||||
|
|
||||||
|
|
|
@ -89,14 +89,14 @@ Example
|
||||||
// Cast the result of the closure so blueprint knows it's a string
|
// Cast the result of the closure so blueprint knows it's a string
|
||||||
label: bind $format_bytes(template.file-size) as <string>
|
label: bind $format_bytes(template.file-size) as <string>
|
||||||
|
|
||||||
.. _Syntax ExprValue:
|
.. _Syntax ExprLiteral:
|
||||||
|
|
||||||
Expression Values
|
Expression Literals
|
||||||
-----------------
|
-------------------
|
||||||
|
|
||||||
.. rst-class:: grammar-block
|
.. rst-class:: grammar-block
|
||||||
|
|
||||||
ExprValue = 'expr' :ref:`Expression<Syntax Expression>`
|
ExprLiteral = 'expr' :ref:`Expression<Syntax Expression>`
|
||||||
|
|
||||||
Some APIs take *an expression itself*--not its result--as a property value. For example, `Gtk.BoolFilter <https://docs.gtk.org/gtk4/class.BoolFilter.html>`_ has an ``expression`` property of type `Gtk.Expression <https://docs.gtk.org/gtk4/class.Expression.html>`_. This expression is evaluated for every item in a list model to determine whether the item should be filtered.
|
Some APIs take *an expression itself*--not its result--as a property value. For example, `Gtk.BoolFilter <https://docs.gtk.org/gtk4/class.BoolFilter.html>`_ has an ``expression`` property of type `Gtk.Expression <https://docs.gtk.org/gtk4/class.Expression.html>`_. This expression is evaluated for every item in a list model to determine whether the item should be filtered.
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ Properties
|
||||||
|
|
||||||
.. rst-class:: grammar-block
|
.. rst-class:: grammar-block
|
||||||
|
|
||||||
Property = <name::ref:`IDENT<Syntax IDENT>`> ':' ( :ref:`Binding<Syntax Binding>` | :ref:`ExprValue<Syntax ExprValue>` | :ref:`ObjectValue<Syntax ObjectValue>` | :ref:`Value<Syntax Value>` ) ';'
|
Property = <name::ref:`IDENT<Syntax IDENT>`> ':' ( :ref:`Binding<Syntax Binding>` | :ref:`ObjectValue<Syntax ObjectValue>` | :ref:`Value<Syntax Value>` ) ';'
|
||||||
|
|
||||||
Properties specify the details of each object, like a label's text, an image's icon name, or the margins on a container.
|
Properties specify the details of each object, like a label's text, an image's icon name, or the margins on a container.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
using Gtk 4.0;
|
|
||||||
|
|
||||||
Label {
|
|
||||||
notify::
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
5,1,0,Expected a signal detail name
|
|
||||||
4,9,3,Unexpected tokens
|
|
|
@ -198,7 +198,7 @@ class TestSamples(unittest.TestCase):
|
||||||
"adw_breakpoint_template",
|
"adw_breakpoint_template",
|
||||||
"expr_closure",
|
"expr_closure",
|
||||||
"expr_closure_args",
|
"expr_closure_args",
|
||||||
"expr_value_closure",
|
"expr_literal_closure",
|
||||||
"parseable",
|
"parseable",
|
||||||
"signal",
|
"signal",
|
||||||
"signal_not_swapped",
|
"signal_not_swapped",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue