mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
Fix template types
This commit is contained in:
parent
64879491a1
commit
88f5b4f1c7
14 changed files with 120 additions and 21 deletions
|
@ -120,7 +120,7 @@ def gtk_object_completer(ast_node, match_variables):
|
|||
matches=new_statement_patterns,
|
||||
)
|
||||
def property_completer(ast_node, match_variables):
|
||||
if ast_node.gir_class and not isinstance(ast_node.gir_class, gir.UncheckedType):
|
||||
if ast_node.gir_class and not isinstance(ast_node.gir_class, gir.ExternType):
|
||||
for prop in ast_node.gir_class.properties:
|
||||
yield Completion(prop, CompletionItemKind.Property, snippet=f"{prop}: $0;")
|
||||
|
||||
|
@ -144,7 +144,7 @@ def prop_value_completer(ast_node, match_variables):
|
|||
matches=new_statement_patterns,
|
||||
)
|
||||
def signal_completer(ast_node, match_variables):
|
||||
if ast_node.gir_class and not isinstance(ast_node.gir_class, gir.UncheckedType):
|
||||
if ast_node.gir_class and not isinstance(ast_node.gir_class, gir.ExternType):
|
||||
for signal in ast_node.gir_class.signals:
|
||||
if not isinstance(ast_node.parent, language.Object):
|
||||
name = "on"
|
||||
|
|
|
@ -114,8 +114,12 @@ class GirType:
|
|||
"""The name of the type in the GObject type system, suitable to pass to `g_type_from_name()`."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@property
|
||||
def incomplete(self) -> bool:
|
||||
return False
|
||||
|
||||
class UncheckedType(GirType):
|
||||
|
||||
class ExternType(GirType):
|
||||
def __init__(self, name: str) -> None:
|
||||
super().__init__()
|
||||
self._name = name
|
||||
|
@ -131,6 +135,10 @@ class UncheckedType(GirType):
|
|||
def glib_type_name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def incomplete(self) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
class ArrayType(GirType):
|
||||
def __init__(self, inner: GirType) -> None:
|
||||
|
@ -507,6 +515,60 @@ class Class(GirNode, GirType):
|
|||
yield from impl.signals.values()
|
||||
|
||||
|
||||
class TemplateType(GirType):
|
||||
def __init__(self, name: str, parent: T.Optional[Class]):
|
||||
self._name = name
|
||||
self.parent = parent
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def full_name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def glib_type_name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@cached_property
|
||||
def properties(self) -> T.Mapping[str, Property]:
|
||||
if self.parent is None or isinstance(self.parent, ExternType):
|
||||
return {}
|
||||
else:
|
||||
return self.parent.properties
|
||||
|
||||
@cached_property
|
||||
def signals(self) -> T.Mapping[str, Signal]:
|
||||
if self.parent is None or isinstance(self.parent, ExternType):
|
||||
return {}
|
||||
else:
|
||||
return self.parent.signals
|
||||
|
||||
def assignable_to(self, other: "GirType") -> bool:
|
||||
if self == other:
|
||||
return True
|
||||
elif isinstance(other, Interface):
|
||||
# we don't know the template type's interfaces, assume yes
|
||||
return True
|
||||
elif self.parent is None or isinstance(self.parent, ExternType):
|
||||
return isinstance(other, Class)
|
||||
else:
|
||||
return self.parent.assignable_to(other)
|
||||
|
||||
@cached_property
|
||||
def signature(self) -> str:
|
||||
if self.parent is None:
|
||||
return f"template {self.name}"
|
||||
else:
|
||||
return f"template {self.name} : {self.parent.full_name}"
|
||||
|
||||
@property
|
||||
def incomplete(self) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
class EnumMember(GirNode):
|
||||
def __init__(self, enum: "Enumeration", tl: typelib.Typelib) -> None:
|
||||
super().__init__(enum, tl)
|
||||
|
|
|
@ -37,7 +37,7 @@ from ..gir import (
|
|||
FloatType,
|
||||
GirType,
|
||||
Enumeration,
|
||||
UncheckedType,
|
||||
ExternType,
|
||||
)
|
||||
from ..lsp_utils import Completion, CompletionItemKind, SemanticToken, SemanticTokenType
|
||||
from ..parse_tree import *
|
||||
|
|
|
@ -141,7 +141,7 @@ class LookupOp(InfixExpr):
|
|||
],
|
||||
)
|
||||
|
||||
if isinstance(self.lhs.type, UncheckedType) or not self.lhs.type_complete:
|
||||
if self.lhs.type.incomplete:
|
||||
return
|
||||
|
||||
elif not isinstance(self.lhs.type, gir.Class) and not isinstance(
|
||||
|
|
|
@ -46,7 +46,7 @@ class Property(AstNode):
|
|||
|
||||
@property
|
||||
def gir_property(self):
|
||||
if self.gir_class is not None and not isinstance(self.gir_class, UncheckedType):
|
||||
if self.gir_class is not None and not isinstance(self.gir_class, ExternType):
|
||||
return self.gir_class.properties.get(self.tokens["name"])
|
||||
|
||||
@context(ValueTypeCtx)
|
||||
|
@ -75,7 +75,7 @@ class Property(AstNode):
|
|||
|
||||
@validate("name")
|
||||
def property_exists(self):
|
||||
if self.gir_class is None or isinstance(self.gir_class, UncheckedType):
|
||||
if self.gir_class is None or self.gir_class.incomplete:
|
||||
# Objects that we have no gir data on should not be validated
|
||||
# This happens for classes defined by the app itself
|
||||
return
|
||||
|
|
|
@ -72,7 +72,7 @@ class Signal(AstNode):
|
|||
|
||||
@property
|
||||
def gir_signal(self):
|
||||
if self.gir_class is not None and not isinstance(self.gir_class, UncheckedType):
|
||||
if self.gir_class is not None and not isinstance(self.gir_class, ExternType):
|
||||
return self.gir_class.signals.get(self.tokens["name"])
|
||||
|
||||
@property
|
||||
|
@ -90,7 +90,7 @@ class Signal(AstNode):
|
|||
|
||||
@validate("name")
|
||||
def signal_exists(self):
|
||||
if self.gir_class is None or isinstance(self.gir_class, UncheckedType):
|
||||
if self.gir_class is None or self.gir_class.incomplete:
|
||||
# Objects that we have no gir data on should not be validated
|
||||
# This happens for classes defined by the app itself
|
||||
return
|
||||
|
|
|
@ -50,11 +50,10 @@ class Template(Object):
|
|||
|
||||
@property
|
||||
def gir_class(self):
|
||||
# Templates might not have a parent class defined
|
||||
if class_name := self.class_name:
|
||||
return class_name.gir_type
|
||||
if self.class_name is None:
|
||||
return gir.TemplateType(self.id, None)
|
||||
else:
|
||||
return gir.UncheckedType(self.id)
|
||||
return gir.TemplateType(self.id, self.class_name.gir_type)
|
||||
|
||||
@validate("id")
|
||||
def unique_in_parent(self):
|
||||
|
|
|
@ -108,11 +108,7 @@ class PropertyBinding(AstNode):
|
|||
|
||||
gir_class = self.source_obj.gir_class
|
||||
|
||||
if (
|
||||
isinstance(self.source_obj, Template)
|
||||
or gir_class is None
|
||||
or isinstance(gir_class, UncheckedType)
|
||||
):
|
||||
if gir_class is None or gir_class.incomplete:
|
||||
# Objects that we have no gir data on should not be validated
|
||||
# This happens for classes defined by the app itself
|
||||
return
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
import typing as T
|
||||
from .common import *
|
||||
from ..gir import Class, Interface
|
||||
from ..gir import Class, ExternType, Interface
|
||||
|
||||
|
||||
class TypeName(AstNode):
|
||||
|
@ -70,7 +70,7 @@ class TypeName(AstNode):
|
|||
self.tokens["class_name"], self.tokens["namespace"]
|
||||
)
|
||||
|
||||
return gir.UncheckedType(self.tokens["class_name"])
|
||||
return gir.ExternType(self.tokens["class_name"])
|
||||
|
||||
@property
|
||||
def glib_type_name(self) -> str:
|
||||
|
@ -95,7 +95,7 @@ class ClassName(TypeName):
|
|||
def gir_class_exists(self):
|
||||
if (
|
||||
self.gir_type is not None
|
||||
and not isinstance(self.gir_type, UncheckedType)
|
||||
and not isinstance(self.gir_type, ExternType)
|
||||
and not isinstance(self.gir_type, Class)
|
||||
):
|
||||
if isinstance(self.gir_type, Interface):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue