From 0b402db4d5567a9c3319dab8880cdccfe18840cf Mon Sep 17 00:00:00 2001 From: James Westman Date: Sun, 25 Dec 2022 16:11:17 -0600 Subject: [PATCH] language: Change extern type syntax Use a '$' instead of a '.' to indicate a type provided in application code. The reason for the change is to have a consistent "extern" symbol that isn't widely used elsewhere and isn't ambiguous in expressions. --- blueprintcompiler/errors.py | 5 +++++ blueprintcompiler/language/common.py | 8 +++++++- blueprintcompiler/language/gobject_object.py | 2 +- blueprintcompiler/language/types.py | 20 ++++++++++++++------ blueprintcompiler/utils.py | 1 + tests/sample_errors/warn_old_extern.blp | 5 +++++ tests/sample_errors/warn_old_extern.err | 2 ++ tests/samples/typeof.blp | 2 +- tests/samples/unchecked_class.blp | 4 ++-- tests/samples/unchecked_class_dec.blp | 4 ++-- tests/test_samples.py | 1 + 11 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 tests/sample_errors/warn_old_extern.blp create mode 100644 tests/sample_errors/warn_old_extern.err diff --git a/blueprintcompiler/errors.py b/blueprintcompiler/errors.py index 816bd4a..01f9066 100644 --- a/blueprintcompiler/errors.py +++ b/blueprintcompiler/errors.py @@ -124,6 +124,11 @@ class CompileWarning(CompileError): color = Colors.YELLOW +class UpgradeWarning(CompileWarning): + category = "upgrade" + color = Colors.PURPLE + + class UnexpectedTokenError(CompileError): def __init__(self, start, end): super().__init__("Unexpected tokens", start, end) diff --git a/blueprintcompiler/language/common.py b/blueprintcompiler/language/common.py index ec15c7a..8ae8d96 100644 --- a/blueprintcompiler/language/common.py +++ b/blueprintcompiler/language/common.py @@ -20,7 +20,13 @@ from .. import gir from ..ast_utils import AstNode, validate, docs -from ..errors import CompileError, MultipleErrors +from ..errors import ( + CompileError, + MultipleErrors, + UpgradeWarning, + CompileWarning, + CodeAction, +) from ..completions_utils import * from .. import decompiler as decompile from ..decompiler import DecompileCtx, decompiler diff --git a/blueprintcompiler/language/gobject_object.py b/blueprintcompiler/language/gobject_object.py index edf8b2a..a66ffe6 100644 --- a/blueprintcompiler/language/gobject_object.py +++ b/blueprintcompiler/language/gobject_object.py @@ -87,7 +87,7 @@ def validate_parent_type(node, ns: str, name: str, err_msg: str): 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 + decompile.full_name(gir_class) if gir_class is not None else "$" + klass ) if id is None: ctx.print(f"{klass_name} {{") diff --git a/blueprintcompiler/language/types.py b/blueprintcompiler/language/types.py index 3b454bc..e1e715d 100644 --- a/blueprintcompiler/language/types.py +++ b/blueprintcompiler/language/types.py @@ -31,33 +31,41 @@ class TypeName(AstNode): UseIdent("class_name"), ], [ - ".", + AnyOf("$", [".", UseLiteral("old_extern", True)]), UseIdent("class_name"), - UseLiteral("ignore_gir", True), + UseLiteral("extern", True), ], UseIdent("class_name"), ) + @validate() + def old_extern(self): + if self.tokens["old_extern"]: + raise UpgradeWarning( + "Use the '$' extern syntax introduced in blueprint 0.8.0", + actions=[CodeAction("Use '$' syntax", "$" + self.tokens["class_name"])], + ) + @validate("class_name") def type_exists(self): - if not self.tokens["ignore_gir"] and self.gir_ns is not None: + if not self.tokens["extern"] and self.gir_ns is not None: self.root.gir.validate_type( self.tokens["class_name"], self.tokens["namespace"] ) @validate("namespace") def gir_ns_exists(self): - if not self.tokens["ignore_gir"]: + if not self.tokens["extern"]: self.root.gir.validate_ns(self.tokens["namespace"]) @property def gir_ns(self): - if not self.tokens["ignore_gir"]: + if not self.tokens["extern"]: return self.root.gir.namespaces.get(self.tokens["namespace"] or "Gtk") @property def gir_type(self) -> gir.GirType: - if self.tokens["class_name"] and not self.tokens["ignore_gir"]: + if self.tokens["class_name"] and not self.tokens["extern"]: return self.root.gir.get_type( self.tokens["class_name"], self.tokens["namespace"] ) diff --git a/blueprintcompiler/utils.py b/blueprintcompiler/utils.py index 5e939c7..4c4b44a 100644 --- a/blueprintcompiler/utils.py +++ b/blueprintcompiler/utils.py @@ -24,6 +24,7 @@ class Colors: RED = "\033[91m" GREEN = "\033[92m" YELLOW = "\033[33m" + PURPLE = "\033[35m" FAINT = "\033[2m" BOLD = "\033[1m" BLUE = "\033[34m" diff --git a/tests/sample_errors/warn_old_extern.blp b/tests/sample_errors/warn_old_extern.blp new file mode 100644 index 0000000..e50fb0f --- /dev/null +++ b/tests/sample_errors/warn_old_extern.blp @@ -0,0 +1,5 @@ +using Gtk 4.0; + +.MyClass { + prop: typeof(.MyOtherClass); +} \ No newline at end of file diff --git a/tests/sample_errors/warn_old_extern.err b/tests/sample_errors/warn_old_extern.err new file mode 100644 index 0000000..8209d23 --- /dev/null +++ b/tests/sample_errors/warn_old_extern.err @@ -0,0 +1,2 @@ +3,1,8,Use the '$' extern syntax introduced in blueprint 0.8.0 +4,16,13,Use the '$' extern syntax introduced in blueprint 0.8.0 \ No newline at end of file diff --git a/tests/samples/typeof.blp b/tests/samples/typeof.blp index 5c5e2e5..cdc1b46 100644 --- a/tests/samples/typeof.blp +++ b/tests/samples/typeof.blp @@ -7,5 +7,5 @@ Gio.ListStore { } Gio.ListStore { - item-type: typeof(.MyObject); + item-type: typeof($MyObject); } \ No newline at end of file diff --git a/tests/samples/unchecked_class.blp b/tests/samples/unchecked_class.blp index 3be0b04..3003842 100644 --- a/tests/samples/unchecked_class.blp +++ b/tests/samples/unchecked_class.blp @@ -1,7 +1,7 @@ using Gtk 4.0; -.MyComponent component { - .MyComponent2 { +$MyComponent component { + $MyComponent2 { flags-value: a | b; } } diff --git a/tests/samples/unchecked_class_dec.blp b/tests/samples/unchecked_class_dec.blp index 81d342e..dbbfe14 100644 --- a/tests/samples/unchecked_class_dec.blp +++ b/tests/samples/unchecked_class_dec.blp @@ -1,7 +1,7 @@ using Gtk 4.0; -.MyComponent component { - .MyComponent2 { +$MyComponent component { + $MyComponent2 { flags-value: "a|b"; } } diff --git a/tests/test_samples.py b/tests/test_samples.py index 6d809c5..6f8a4eb 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -236,6 +236,7 @@ class TestSamples(unittest.TestCase): self.assert_sample_error("two_templates") self.assert_sample_error("uint") self.assert_sample_error("using_invalid_namespace") + self.assert_sample_error("warn_old_extern") self.assert_sample_error("widgets_in_non_size_group") def test_decompiler(self):