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.
This commit is contained in:
James Westman 2022-12-25 16:11:17 -06:00
parent be284de879
commit 0b402db4d5
No known key found for this signature in database
GPG key ID: CE2DBA0ADB654EA6
11 changed files with 41 additions and 13 deletions

View file

@ -124,6 +124,11 @@ class CompileWarning(CompileError):
color = Colors.YELLOW color = Colors.YELLOW
class UpgradeWarning(CompileWarning):
category = "upgrade"
color = Colors.PURPLE
class UnexpectedTokenError(CompileError): class UnexpectedTokenError(CompileError):
def __init__(self, start, end): def __init__(self, start, end):
super().__init__("Unexpected tokens", start, end) super().__init__("Unexpected tokens", start, end)

View file

@ -20,7 +20,13 @@
from .. import gir from .. import gir
from ..ast_utils import AstNode, validate, docs 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 ..completions_utils import *
from .. import decompiler as decompile from .. import decompiler as decompile
from ..decompiler import DecompileCtx, decompiler from ..decompiler import DecompileCtx, decompiler

View file

@ -87,7 +87,7 @@ def validate_parent_type(node, ns: str, name: str, err_msg: str):
def decompile_object(ctx, gir, klass, id=None): def decompile_object(ctx, gir, klass, id=None):
gir_class = ctx.type_by_cname(klass) gir_class = ctx.type_by_cname(klass)
klass_name = ( 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: if id is None:
ctx.print(f"{klass_name} {{") ctx.print(f"{klass_name} {{")

View file

@ -31,33 +31,41 @@ class TypeName(AstNode):
UseIdent("class_name"), UseIdent("class_name"),
], ],
[ [
".", AnyOf("$", [".", UseLiteral("old_extern", True)]),
UseIdent("class_name"), UseIdent("class_name"),
UseLiteral("ignore_gir", True), UseLiteral("extern", True),
], ],
UseIdent("class_name"), 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") @validate("class_name")
def type_exists(self): 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.root.gir.validate_type(
self.tokens["class_name"], self.tokens["namespace"] self.tokens["class_name"], self.tokens["namespace"]
) )
@validate("namespace") @validate("namespace")
def gir_ns_exists(self): def gir_ns_exists(self):
if not self.tokens["ignore_gir"]: if not self.tokens["extern"]:
self.root.gir.validate_ns(self.tokens["namespace"]) self.root.gir.validate_ns(self.tokens["namespace"])
@property @property
def gir_ns(self): 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") return self.root.gir.namespaces.get(self.tokens["namespace"] or "Gtk")
@property @property
def gir_type(self) -> gir.GirType: 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( return self.root.gir.get_type(
self.tokens["class_name"], self.tokens["namespace"] self.tokens["class_name"], self.tokens["namespace"]
) )

View file

@ -24,6 +24,7 @@ class Colors:
RED = "\033[91m" RED = "\033[91m"
GREEN = "\033[92m" GREEN = "\033[92m"
YELLOW = "\033[33m" YELLOW = "\033[33m"
PURPLE = "\033[35m"
FAINT = "\033[2m" FAINT = "\033[2m"
BOLD = "\033[1m" BOLD = "\033[1m"
BLUE = "\033[34m" BLUE = "\033[34m"

View file

@ -0,0 +1,5 @@
using Gtk 4.0;
.MyClass {
prop: typeof(.MyOtherClass);
}

View file

@ -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

View file

@ -7,5 +7,5 @@ Gio.ListStore {
} }
Gio.ListStore { Gio.ListStore {
item-type: typeof(.MyObject); item-type: typeof($MyObject);
} }

View file

@ -1,7 +1,7 @@
using Gtk 4.0; using Gtk 4.0;
.MyComponent component { $MyComponent component {
.MyComponent2 { $MyComponent2 {
flags-value: a | b; flags-value: a | b;
} }
} }

View file

@ -1,7 +1,7 @@
using Gtk 4.0; using Gtk 4.0;
.MyComponent component { $MyComponent component {
.MyComponent2 { $MyComponent2 {
flags-value: "a|b"; flags-value: "a|b";
} }
} }

View file

@ -236,6 +236,7 @@ class TestSamples(unittest.TestCase):
self.assert_sample_error("two_templates") self.assert_sample_error("two_templates")
self.assert_sample_error("uint") self.assert_sample_error("uint")
self.assert_sample_error("using_invalid_namespace") self.assert_sample_error("using_invalid_namespace")
self.assert_sample_error("warn_old_extern")
self.assert_sample_error("widgets_in_non_size_group") self.assert_sample_error("widgets_in_non_size_group")
def test_decompiler(self): def test_decompiler(self):