diff --git a/blueprintcompiler/language/expression.py b/blueprintcompiler/language/expression.py index de096e3..3958907 100644 --- a/blueprintcompiler/language/expression.py +++ b/blueprintcompiler/language/expression.py @@ -50,12 +50,26 @@ class IdentExpr(AstNode): def is_this(self): return self.parent_by_type(Scope).this_name == self.tokens["ident"] + @validate() + def exists(self): + if self.is_this: + return + + scope = self.parent_by_type(Scope) + if self.tokens["ident"] not in scope.get_objects(): + raise CompileError( + f"Could not find object with ID '{self.tokens['ident']}'", + did_you_mean=(self.tokens['ident'], scope.get_objects().keys()), + ) + @property def gir_type(self): + scope = self.parent_by_type(Scope) + if self.is_this: - return self.parent_by_type(Scope).this_type - else: - return None + return scope.this_type + elif self.tokens["ident"] in scope.get_objects(): + return scope.get_objects()[self.tokens["ident"]].gir_class def emit_xml(self, xml: XmlEmitter): if self.is_this: @@ -95,7 +109,21 @@ class LookupOp(InfixExpr): @property def gir_type(self): - return None + if parent_type := self.lhs.gir_type: + if prop := parent_type.properties.get(self.tokens["property"]): + return prop.type + + @validate("property") + def property_exists(self): + if parent_type := self.lhs.gir_type: + if not (isinstance(parent_type, gir.Class) or isinstance(parent_type, gir.Interface)): + raise CompileError(f"Type {parent_type.full_name} does not have properties") + elif self.tokens["property"] not in parent_type.properties: + raise CompileError( + f"{parent_type.full_name} does not have a property called {self.tokens['property']}", + hints=["Do you need to cast the previous expression?"], + did_you_mean=(self.tokens['property'], parent_type.properties.keys()), + ) def emit_xml(self, xml: XmlEmitter): if isinstance(self.lhs, IdentExpr) and self.lhs.is_this: diff --git a/tests/sample_errors/expr_lookup_prop.blp b/tests/sample_errors/expr_lookup_prop.blp new file mode 100644 index 0000000..1d73ad9 --- /dev/null +++ b/tests/sample_errors/expr_lookup_prop.blp @@ -0,0 +1,9 @@ +using Gtk 4.0; + +Box { + Label label { + visible: bind label.parent.something; + margin-start: bind label.margin-start.other; + label: bind nothing.parent.label; + } +} diff --git a/tests/sample_errors/expr_lookup_prop.err b/tests/sample_errors/expr_lookup_prop.err new file mode 100644 index 0000000..70c6702 --- /dev/null +++ b/tests/sample_errors/expr_lookup_prop.err @@ -0,0 +1,3 @@ +5,32,9,Gtk.Widget does not have a property called something +6,43,5,Type int does not have properties +7,17,7,Could not find object with ID 'nothing' \ No newline at end of file diff --git a/tests/samples/expr_closure.ui b/tests/samples/expr_closure.ui index 27249e6..1ee7eca 100644 --- a/tests/samples/expr_closure.ui +++ b/tests/samples/expr_closure.ui @@ -10,7 +10,7 @@ - + box diff --git a/tests/samples/expr_lookup.blp b/tests/samples/expr_lookup.blp index 3adc9a6..a3d45c8 100644 --- a/tests/samples/expr_lookup.blp +++ b/tests/samples/expr_lookup.blp @@ -5,5 +5,5 @@ Overlay { } Label { - label: bind ((Label) label.parent.child).label; + label: bind ((Label) ((Overlay) label.parent).child).label; } diff --git a/tests/samples/expr_lookup.ui b/tests/samples/expr_lookup.ui index 3ffb78c..91d7590 100644 --- a/tests/samples/expr_lookup.ui +++ b/tests/samples/expr_lookup.ui @@ -9,8 +9,8 @@ - - + + label diff --git a/tests/samples/lambda.ui b/tests/samples/lambda.ui index 177449b..462caea 100644 --- a/tests/samples/lambda.ui +++ b/tests/samples/lambda.ui @@ -8,7 +8,7 @@ - + filter diff --git a/tests/test_samples.py b/tests/test_samples.py index 3d09a63..7f7adfb 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -185,6 +185,7 @@ class TestSamples(unittest.TestCase): self.assert_sample_error("does_not_implement") self.assert_sample_error("duplicate_obj_id") self.assert_sample_error("enum_member_dne") + self.assert_sample_error("expr_lookup_prop") self.assert_sample_error("filters_in_non_file_filter") self.assert_sample_error("gtk_3") self.assert_sample_error("gtk_exact_version")