completions: Lookup expressions

This commit is contained in:
James Westman 2025-05-15 19:56:10 -05:00
parent 684ed7dc02
commit ddcd77f212
No known key found for this signature in database
GPG key ID: CE2DBA0ADB654EA6
2 changed files with 43 additions and 16 deletions

View file

@ -80,20 +80,24 @@ class Binding(AstNode):
@property @property
def simple_binding(self) -> T.Optional["SimpleBinding"]: def simple_binding(self) -> T.Optional["SimpleBinding"]:
if isinstance(self.expression.last, LookupOp): from .values import IdentLiteral
if isinstance(self.expression.last.lhs, LiteralExpr):
from .values import IdentLiteral
if isinstance(self.expression.last.lhs.literal.value, IdentLiteral): if (
flags = [x.flag for x in self.flags] not isinstance(self.expression.last, LookupOp)
return SimpleBinding( or not isinstance(self.expression.last.lhs, LiteralExpr)
self.expression.last.lhs.literal.value.ident, or not isinstance(self.expression.last.lhs.literal.value, IdentLiteral)
self.expression.last.property_name, or self.expression.last.property_name is None
no_sync_create="no-sync-create" in flags, ):
bidirectional="bidirectional" in flags, return None
inverted="inverted" in flags,
) flags = [x.flag for x in self.flags]
return None return SimpleBinding(
self.expression.last.lhs.literal.value.ident,
self.expression.last.property_name,
no_sync_create="no-sync-create" in flags,
bidirectional="bidirectional" in flags,
inverted="inverted" in flags,
)
@validate("bind") @validate("bind")
def bind_property(self): def bind_property(self):

View file

@ -18,6 +18,7 @@
# SPDX-License-Identifier: LGPL-3.0-or-later # SPDX-License-Identifier: LGPL-3.0-or-later
from .. import annotations
from ..decompiler import decompile_element from ..decompiler import decompile_element
from .common import * from .common import *
from .contexts import ScopeCtx, ValueTypeCtx from .contexts import ScopeCtx, ValueTypeCtx
@ -112,18 +113,21 @@ class LiteralExpr(ExprBase):
class LookupOp(InfixExpr): class LookupOp(InfixExpr):
grammar = [".", UseIdent("property")] grammar = [".", UseIdent("property").expected("property name")]
@context(ValueTypeCtx) @context(ValueTypeCtx)
def value_type(self) -> ValueTypeCtx: def value_type(self) -> ValueTypeCtx:
return ValueTypeCtx(None, must_infer_type=True) return ValueTypeCtx(None, must_infer_type=True)
@property @property
def property_name(self) -> str: def property_name(self) -> T.Optional[str]:
return self.tokens["property"] return self.tokens["property"]
@property @property
def type(self) -> T.Optional[GirType]: def type(self) -> T.Optional[GirType]:
if self.property_name is None:
return None
if isinstance(self.lhs.type, gir.Class) or isinstance( if isinstance(self.lhs.type, gir.Class) or isinstance(
self.lhs.type, gir.Interface self.lhs.type, gir.Interface
): ):
@ -167,7 +171,10 @@ class LookupOp(InfixExpr):
f"Type {self.lhs.type.full_name} does not have properties" f"Type {self.lhs.type.full_name} does not have properties"
) )
elif self.lhs.type.properties.get(self.property_name) is None: elif (
self.property_name is not None
and self.lhs.type.properties.get(self.property_name) is None
):
raise CompileError( raise CompileError(
f"{self.lhs.type.full_name} does not have a property called {self.property_name}", f"{self.lhs.type.full_name} does not have a property called {self.property_name}",
did_you_mean=(self.property_name, self.lhs.type.properties.keys()), did_you_mean=(self.property_name, self.lhs.type.properties.keys()),
@ -192,6 +199,22 @@ class LookupOp(InfixExpr):
) )
@completer([LookupOp], ["."])
def complete_lookup_property(ctx: CompletionContext):
assert isinstance(ctx.ast_node, LookupOp)
t = ctx.ast_node.lhs.type
if t is not None and hasattr(t, "properties"):
for prop_name, prop in t.properties.items():
yield Completion(
prop_name,
CompletionItemKind.Property,
deprecated=prop.deprecated,
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, prop_name),
docs=prop.doc,
)
class CastExpr(InfixExpr): class CastExpr(InfixExpr):
grammar = [ grammar = [
Keyword("as"), Keyword("as"),