Emit deprecation warnings

This commit is contained in:
James Westman 2023-07-23 18:04:10 -05:00
parent 8fab7c1706
commit 94db929f74
9 changed files with 102 additions and 2 deletions

View file

@ -136,6 +136,14 @@ class GirType:
def incomplete(self) -> bool: def incomplete(self) -> bool:
return False return False
@property
def deprecated(self) -> bool:
return False
@property
def deprecated_doc(self) -> T.Optional[str]:
return None
class ExternType(GirType): class ExternType(GirType):
def __init__(self, name: str) -> None: def __init__(self, name: str) -> None:
@ -330,6 +338,13 @@ class GirNode:
def type(self) -> GirType: def type(self) -> GirType:
raise NotImplementedError() raise NotImplementedError()
@property
def deprecated_doc(self) -> T.Optional[str]:
try:
return self.xml.get_elements("doc-deprecated")[0].cdata.strip()
except:
return None
class Property(GirNode): class Property(GirNode):
xml_tag = "property" xml_tag = "property"
@ -365,6 +380,10 @@ class Property(GirNode):
else: else:
return None return None
@property
def deprecated(self) -> bool:
return self.tl.PROP_DEPRECATED == 1
class Argument(GirNode): class Argument(GirNode):
def __init__(self, container: GirNode, tl: typelib.Typelib) -> None: def __init__(self, container: GirNode, tl: typelib.Typelib) -> None:
@ -427,6 +446,10 @@ class Signal(GirNode):
else: else:
return None return None
@property
def deprecated(self) -> bool:
return self.tl.SIGNAL_DEPRECATED == 1
class Interface(GirNode, GirType): class Interface(GirNode, GirType):
xml_tag = "interface" xml_tag = "interface"
@ -488,6 +511,10 @@ class Interface(GirNode, GirType):
else: else:
return None return None
@property
def deprecated(self) -> bool:
return self.tl.INTERFACE_DEPRECATED == 1
class Class(GirNode, GirType): class Class(GirNode, GirType):
xml_tag = "class" xml_tag = "class"
@ -609,6 +636,10 @@ class Class(GirNode, GirType):
else: else:
return None return None
@property
def deprecated(self) -> bool:
return self.tl.OBJ_DEPRECATED == 1
class TemplateType(GirType): class TemplateType(GirType):
def __init__(self, name: str, parent: T.Optional[GirType]): def __init__(self, name: str, parent: T.Optional[GirType]):
@ -722,6 +753,10 @@ class Enumeration(GirNode, GirType):
else: else:
return None return None
@property
def deprecated(self) -> bool:
return self.tl.ENUM_DEPRECATED == 1
class Boxed(GirNode, GirType): class Boxed(GirNode, GirType):
xml_tag = "glib:boxed" xml_tag = "glib:boxed"
@ -743,6 +778,10 @@ class Boxed(GirNode, GirType):
else: else:
return None return None
@property
def deprecated(self) -> bool:
return self.tl.STRUCT_DEPRECATED == 1
class Bitfield(Enumeration): class Bitfield(Enumeration):
xml_tag = "bitfield" xml_tag = "bitfield"

View file

@ -41,9 +41,11 @@ class Property(AstNode):
return self.parent.parent.gir_class return self.parent.parent.gir_class
@property @property
def gir_property(self): def gir_property(self) -> T.Optional[gir.Property]:
if self.gir_class is not None and not isinstance(self.gir_class, ExternType): if self.gir_class is not None and not isinstance(self.gir_class, ExternType):
return self.gir_class.properties.get(self.tokens["name"]) return self.gir_class.properties.get(self.tokens["name"])
else:
return None
@validate() @validate()
def binding_valid(self): def binding_valid(self):
@ -91,6 +93,17 @@ class Property(AstNode):
check=lambda child: child.tokens["name"] == self.tokens["name"], check=lambda child: child.tokens["name"] == self.tokens["name"],
) )
@validate("name")
def deprecated(self) -> None:
if self.gir_property is not None and self.gir_property.deprecated:
hints = []
if self.gir_property.deprecated_doc:
hints.append(self.gir_property.deprecated_doc)
raise CompileWarning(
f"{self.gir_property.signature} is deprecated",
hints=hints,
)
@docs("name") @docs("name")
def property_docs(self): def property_docs(self):
if self.gir_property is not None: if self.gir_property is not None:

View file

@ -95,9 +95,11 @@ class Signal(AstNode):
return any(x.flag == "after" for x in self.flags) return any(x.flag == "after" for x in self.flags)
@property @property
def gir_signal(self): def gir_signal(self) -> T.Optional[gir.Signal]:
if self.gir_class is not None and not isinstance(self.gir_class, ExternType): if self.gir_class is not None and not isinstance(self.gir_class, ExternType):
return self.gir_class.signals.get(self.tokens["name"]) return self.gir_class.signals.get(self.tokens["name"])
else:
return None
@property @property
def gir_class(self): def gir_class(self):
@ -134,6 +136,17 @@ class Signal(AstNode):
if self.context[ScopeCtx].objects.get(object_id) is None: if self.context[ScopeCtx].objects.get(object_id) is None:
raise CompileError(f"Could not find object with ID '{object_id}'") raise CompileError(f"Could not find object with ID '{object_id}'")
@validate("name")
def deprecated(self) -> None:
if self.gir_signal is not None and self.gir_signal.deprecated:
hints = []
if self.gir_signal.deprecated_doc:
hints.append(self.gir_signal.deprecated_doc)
raise CompileWarning(
f"{self.gir_signal.signature} is deprecated",
hints=hints,
)
@docs("name") @docs("name")
def signal_docs(self): def signal_docs(self):
if self.gir_signal is not None: if self.gir_signal is not None:

View file

@ -57,6 +57,17 @@ class TypeName(AstNode):
if not self.tokens["extern"]: if not self.tokens["extern"]:
self.root.gir.validate_ns(self.tokens["namespace"]) self.root.gir.validate_ns(self.tokens["namespace"])
@validate()
def deprecated(self) -> None:
if self.gir_type and self.gir_type.deprecated:
hints = []
if self.gir_type.deprecated_doc:
hints.append(self.gir_type.deprecated_doc)
raise CompileWarning(
f"{self.gir_type.full_name} is deprecated",
hints=hints,
)
@property @property
def gir_ns(self): def gir_ns(self):
if not self.tokens["extern"]: if not self.tokens["extern"]:

View file

@ -150,11 +150,15 @@ class Typelib:
BLOB_NAME = Field(0x4, "string") BLOB_NAME = Field(0x4, "string")
STRUCT_DEPRECATED = Field(0x2, "u16", 0, 1)
ENUM_DEPRECATED = Field(0x2, "u16", 0, 1)
ENUM_GTYPE_NAME = Field(0x8, "string") ENUM_GTYPE_NAME = Field(0x8, "string")
ENUM_N_VALUES = Field(0x10, "u16") ENUM_N_VALUES = Field(0x10, "u16")
ENUM_N_METHODS = Field(0x12, "u16") ENUM_N_METHODS = Field(0x12, "u16")
ENUM_VALUES = Field(0x18, "offset") ENUM_VALUES = Field(0x18, "offset")
INTERFACE_DEPRECATED = Field(0x2, "u16", 0, 1)
INTERFACE_GTYPE_NAME = Field(0x8, "string") INTERFACE_GTYPE_NAME = Field(0x8, "string")
INTERFACE_N_PREREQUISITES = Field(0x12, "u16") INTERFACE_N_PREREQUISITES = Field(0x12, "u16")
INTERFACE_N_PROPERTIES = Field(0x14, "u16") INTERFACE_N_PROPERTIES = Field(0x14, "u16")

View file

@ -0,0 +1,10 @@
using Gtk 4.0;
using Gio 2.0;
Dialog {
use-header-bar: 1;
}
Window {
keys-changed => $on_window_keys_changed();
}

View file

@ -0,0 +1 @@
4,1,6,Gtk.Dialog is deprecated

View file

@ -1,2 +1,3 @@
3,10,12,Use type syntax here (introduced in blueprint 0.8.0) 3,10,12,Use type syntax here (introduced in blueprint 0.8.0)
8,1,6,Gtk.Dialog is deprecated
9,18,12,Use 'template' instead of the class name (introduced in 0.8.0) 9,18,12,Use 'template' instead of the class name (introduced in 0.8.0)

View file

@ -54,6 +54,14 @@ class TestSamples(unittest.TestCase):
tokens = tokenizer.tokenize(blueprint) tokens = tokenizer.tokenize(blueprint)
ast, errors, warnings = parser.parse(tokens) ast, errors, warnings = parser.parse(tokens)
# Ignore deprecation warnings because some of the things we're testing
# are deprecated
warnings = [
warning
for warning in warnings
if "is deprecated" not in warning.message
]
if errors: if errors:
raise errors raise errors
if len(warnings): if len(warnings):