mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-06-22 23:19:25 -04:00
Merge branch 'completion-improvements' into 'main'
Completion improvements See merge request GNOME/blueprint-compiler!243
This commit is contained in:
commit
90b60e4de7
39 changed files with 814 additions and 268 deletions
|
@ -34,10 +34,17 @@ from .gtk_scale import ExtScaleMarks
|
|||
from .gtk_size_group import ExtSizeGroupWidgets
|
||||
from .gtk_string_list import ExtStringListStrings
|
||||
from .gtk_styles import ExtStyles
|
||||
from .gtkbuilder_child import Child, ChildExtension, ChildInternal, ChildType
|
||||
from .gtkbuilder_child import (
|
||||
Child,
|
||||
ChildAnnotation,
|
||||
ChildExtension,
|
||||
ChildInternal,
|
||||
ChildType,
|
||||
)
|
||||
from .gtkbuilder_template import Template
|
||||
from .imports import GtkDirective, Import
|
||||
from .types import ClassName
|
||||
from .response_id import ExtResponse
|
||||
from .types import BracketedTypeName, ClassName, TypeName
|
||||
from .ui import UI
|
||||
from .values import (
|
||||
ArrayValue,
|
||||
|
|
|
@ -140,21 +140,10 @@ class ExtAdwResponseDialog(AstNode):
|
|||
|
||||
@completer(
|
||||
applies_in=[ObjectContent],
|
||||
applies_in_subclass=("Adw", "MessageDialog"),
|
||||
applies_in_subclass=[("Adw", "AlertDialog"), ("Adw", "MessageDialog")],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def complete_adw_message_dialog(lsp, ast_node, match_variables):
|
||||
yield Completion(
|
||||
"responses", CompletionItemKind.Keyword, snippet="responses [\n\t$0\n]"
|
||||
)
|
||||
|
||||
|
||||
@completer(
|
||||
applies_in=[ObjectContent],
|
||||
applies_in_subclass=("Adw", "AlertDialog"),
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def complete_adw_alert_dialog(lsp, ast_node, match_variables):
|
||||
def complete_adw_message_dialog(_ctx: CompletionContext):
|
||||
yield Completion(
|
||||
"responses", CompletionItemKind.Keyword, snippet="responses [\n\t$0\n]"
|
||||
)
|
||||
|
|
|
@ -34,6 +34,7 @@ from ..errors import (
|
|||
CompileError,
|
||||
CompileWarning,
|
||||
DeprecatedWarning,
|
||||
ErrorReference,
|
||||
MultipleErrors,
|
||||
UnusedWarning,
|
||||
UpgradeWarning,
|
||||
|
|
|
@ -48,7 +48,7 @@ class ScopeCtx:
|
|||
return self.node
|
||||
|
||||
@cached_property
|
||||
def objects(self) -> T.Dict[str, Object]:
|
||||
def objects(self) -> T.Dict[str, AstNode]:
|
||||
return {
|
||||
obj.tokens["id"]: obj
|
||||
for obj in self._iter_recursive(self.node)
|
||||
|
@ -58,7 +58,7 @@ class ScopeCtx:
|
|||
def validate_unique_ids(self) -> None:
|
||||
from .gtk_list_item_factory import ExtListItemFactory
|
||||
|
||||
passed = {}
|
||||
passed: T.Dict[str, AstNode] = {}
|
||||
for obj in self._iter_recursive(self.node):
|
||||
from .gtk_menu import Menu
|
||||
|
||||
|
@ -73,10 +73,16 @@ class ScopeCtx:
|
|||
raise CompileError(
|
||||
f"Duplicate object ID '{obj.id}'",
|
||||
token.range,
|
||||
references=[
|
||||
ErrorReference(
|
||||
passed[obj.tokens["id"]].group.tokens["id"].range,
|
||||
"previous declaration was here",
|
||||
)
|
||||
],
|
||||
)
|
||||
passed[obj.id] = obj
|
||||
|
||||
def _iter_recursive(self, node: AstNode):
|
||||
def _iter_recursive(self, node: AstNode) -> T.Generator[AstNode, T.Any, None]:
|
||||
yield node
|
||||
for child in node.children:
|
||||
if child.context[ScopeCtx] is self:
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
from ..decompiler import decompile_element
|
||||
from .common import *
|
||||
from .contexts import ScopeCtx, ValueTypeCtx
|
||||
from .types import TypeName
|
||||
from .types import BracketedTypeName, TypeName
|
||||
|
||||
expr = Sequence()
|
||||
|
||||
|
@ -196,7 +196,7 @@ class CastExpr(InfixExpr):
|
|||
grammar = [
|
||||
Keyword("as"),
|
||||
AnyOf(
|
||||
["<", TypeName, Match(">").expected()],
|
||||
BracketedTypeName,
|
||||
[
|
||||
UseExact("lparen", "("),
|
||||
TypeName,
|
||||
|
@ -211,7 +211,13 @@ class CastExpr(InfixExpr):
|
|||
|
||||
@property
|
||||
def type(self) -> T.Optional[GirType]:
|
||||
return self.children[TypeName][0].gir_type
|
||||
if len(self.children[BracketedTypeName]) == 1:
|
||||
type_name = self.children[BracketedTypeName][0].type_name
|
||||
return None if type_name is None else type_name.gir_type
|
||||
elif len(self.children[TypeName]) == 1:
|
||||
return self.children[TypeName][0].gir_type
|
||||
else:
|
||||
return None
|
||||
|
||||
@validate()
|
||||
def cast_makes_sense(self):
|
||||
|
|
|
@ -26,7 +26,11 @@ from .values import ArrayValue, ExprValue, ObjectValue, Value
|
|||
|
||||
class Property(AstNode):
|
||||
grammar = Statement(
|
||||
UseIdent("name"), ":", AnyOf(Binding, ExprValue, ObjectValue, Value, ArrayValue)
|
||||
UseIdent("name"),
|
||||
":",
|
||||
AnyOf(Binding, ExprValue, ObjectValue, Value, ArrayValue).expected(
|
||||
"property value"
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
|
|
|
@ -247,3 +247,11 @@ def decompile_signal(
|
|||
line += ";"
|
||||
ctx.print(line)
|
||||
return gir
|
||||
|
||||
|
||||
@completer(
|
||||
[Signal],
|
||||
[[(TokenType.PUNCTUATION, "(")]],
|
||||
)
|
||||
def signal_object_completer(ctx: CompletionContext):
|
||||
yield from get_object_id_completions(ctx)
|
||||
|
|
|
@ -25,12 +25,13 @@ from .gobject_object import ObjectContent, validate_parent_type
|
|||
from .values import Value
|
||||
|
||||
|
||||
def get_property_types(gir):
|
||||
def get_property_types(gir: gir.GirContext) -> T.Dict[str, T.Optional[GirType]]:
|
||||
# from <https://docs.gtk.org/gtk4/enum.AccessibleProperty.html>
|
||||
return {
|
||||
"autocomplete": gir.get_type("AccessibleAutocomplete", "Gtk"),
|
||||
"description": StringType(),
|
||||
"has-popup": BoolType(),
|
||||
"help-text": StringType(),
|
||||
"key-shortcuts": StringType(),
|
||||
"label": StringType(),
|
||||
"level": IntType(),
|
||||
|
@ -50,7 +51,7 @@ def get_property_types(gir):
|
|||
}
|
||||
|
||||
|
||||
def get_relation_types(gir):
|
||||
def get_relation_types(gir: gir.GirContext) -> T.Dict[str, T.Optional[GirType]]:
|
||||
# from <https://docs.gtk.org/gtk4/enum.AccessibleRelation.html>
|
||||
widget = gir.get_type("Widget", "Gtk")
|
||||
return {
|
||||
|
@ -75,7 +76,7 @@ def get_relation_types(gir):
|
|||
}
|
||||
|
||||
|
||||
def get_state_types(gir):
|
||||
def get_state_types(gir: gir.GirContext) -> T.Dict[str, T.Optional[GirType]]:
|
||||
# from <https://docs.gtk.org/gtk4/enum.AccessibleState.html>
|
||||
return {
|
||||
"busy": BoolType(),
|
||||
|
@ -86,9 +87,24 @@ def get_state_types(gir):
|
|||
"invalid": gir.get_type("AccessibleInvalidState", "Gtk"),
|
||||
"pressed": gir.get_type("AccessibleTristate", "Gtk"),
|
||||
"selected": BoolType(),
|
||||
"visited": BoolType(),
|
||||
}
|
||||
|
||||
|
||||
TRANSLATED = set(
|
||||
[
|
||||
"description",
|
||||
"help-text",
|
||||
"label",
|
||||
"placeholder",
|
||||
"role-description",
|
||||
"value-text",
|
||||
"col-index-text",
|
||||
"row-index-text",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def get_types(gir):
|
||||
return {
|
||||
**get_property_types(gir),
|
||||
|
@ -121,7 +137,9 @@ class A11yProperty(AstNode):
|
|||
grammar = Statement(
|
||||
UseIdent("name"),
|
||||
":",
|
||||
AnyOf(Value, ["[", UseLiteral("list_form", True), Delimited(Value, ","), "]"]),
|
||||
AnyOf(
|
||||
Value, ["[", UseLiteral("list_form", True), Delimited(Value, ","), "]"]
|
||||
).expected("value"),
|
||||
)
|
||||
|
||||
@property
|
||||
|
@ -232,9 +250,12 @@ class ExtAccessibility(AstNode):
|
|||
applies_in=[ObjectContent],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def a11y_completer(lsp, ast_node, match_variables):
|
||||
def a11y_completer(_ctx: CompletionContext):
|
||||
yield Completion(
|
||||
"accessibility", CompletionItemKind.Snippet, snippet="accessibility {\n $0\n}"
|
||||
"accessibility",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet="accessibility {\n $0\n}",
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "accessibility"),
|
||||
)
|
||||
|
||||
|
||||
|
@ -242,12 +263,14 @@ def a11y_completer(lsp, ast_node, match_variables):
|
|||
applies_in=[ExtAccessibility],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def a11y_name_completer(lsp, ast_node, match_variables):
|
||||
for name, type in get_types(ast_node.root.gir).items():
|
||||
yield Completion(
|
||||
def a11y_property_completer(ctx: CompletionContext):
|
||||
for name, type in get_types(ctx.ast_node.root.gir).items():
|
||||
yield get_property_completion(
|
||||
name,
|
||||
CompletionItemKind.Property,
|
||||
docs=_get_docs(ast_node.root.gir, type.name),
|
||||
type,
|
||||
ctx,
|
||||
name in TRANSLATED,
|
||||
_get_docs(ctx.ast_node.root.gir, name),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -91,11 +91,16 @@ class ExtComboBoxItems(AstNode):
|
|||
|
||||
@completer(
|
||||
applies_in=[ObjectContent],
|
||||
applies_in_subclass=("Gtk", "ComboBoxText"),
|
||||
applies_in_subclass=[("Gtk", "ComboBoxText")],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def items_completer(lsp, ast_node, match_variables):
|
||||
yield Completion("items", CompletionItemKind.Snippet, snippet="items [$0]")
|
||||
def items_completer(_ctx: CompletionContext):
|
||||
yield Completion(
|
||||
"items",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet="items [$0]",
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "items"),
|
||||
)
|
||||
|
||||
|
||||
@decompiler("items", parent_type="Gtk.ComboBoxText")
|
||||
|
|
|
@ -98,15 +98,28 @@ ext_file_filter_suffixes = create_node("suffixes", "suffix")
|
|||
|
||||
@completer(
|
||||
applies_in=[ObjectContent],
|
||||
applies_in_subclass=("Gtk", "FileFilter"),
|
||||
applies_in_subclass=[("Gtk", "FileFilter")],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def file_filter_completer(lsp, ast_node, match_variables):
|
||||
def file_filter_completer(_ctx: CompletionContext):
|
||||
yield Completion(
|
||||
"mime-types", CompletionItemKind.Snippet, snippet='mime-types ["$0"]'
|
||||
"mime-types",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet='mime-types ["$0"]',
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "mime-types"),
|
||||
)
|
||||
yield Completion(
|
||||
"patterns",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet='patterns ["$0"]',
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "patterns"),
|
||||
)
|
||||
yield Completion(
|
||||
"suffixes",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet='suffixes ["$0"]',
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "suffixes"),
|
||||
)
|
||||
yield Completion("patterns", CompletionItemKind.Snippet, snippet='patterns ["$0"]')
|
||||
yield Completion("suffixes", CompletionItemKind.Snippet, snippet='suffixes ["$0"]')
|
||||
|
||||
|
||||
@decompiler("mime-types")
|
||||
|
|
|
@ -90,11 +90,16 @@ class ExtLayout(AstNode):
|
|||
|
||||
@completer(
|
||||
applies_in=[ObjectContent],
|
||||
applies_in_subclass=("Gtk", "Widget"),
|
||||
applies_in_subclass=[("Gtk", "Widget")],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def layout_completer(lsp, ast_node, match_variables):
|
||||
yield Completion("layout", CompletionItemKind.Snippet, snippet="layout {\n $0\n}")
|
||||
def layout_completer(_ctx: CompletionContext):
|
||||
yield Completion(
|
||||
"layout",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet="layout {\n $0\n}",
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "layout"),
|
||||
)
|
||||
|
||||
|
||||
@decompiler("layout")
|
||||
|
|
|
@ -243,7 +243,7 @@ from .ui import UI
|
|||
applies_in=[UI],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def menu_completer(lsp, ast_node, match_variables):
|
||||
def menu_completer(_ctx: CompletionContext):
|
||||
yield Completion("menu", CompletionItemKind.Snippet, snippet="menu {\n $0\n}")
|
||||
|
||||
|
||||
|
@ -251,23 +251,50 @@ def menu_completer(lsp, ast_node, match_variables):
|
|||
applies_in=[Menu],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def menu_content_completer(lsp, ast_node, match_variables):
|
||||
def menu_content_completer(_ctx: CompletionContext):
|
||||
yield Completion(
|
||||
"submenu", CompletionItemKind.Snippet, snippet="submenu {\n $0\n}"
|
||||
"submenu",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet="submenu {\n $0\n}",
|
||||
sort_text=get_sort_key(CompletionPriority.CLASS, "1 submenu"),
|
||||
)
|
||||
yield Completion(
|
||||
"section", CompletionItemKind.Snippet, snippet="section {\n $0\n}"
|
||||
"section",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet="section {\n $0\n}",
|
||||
sort_text=get_sort_key(CompletionPriority.CLASS, "1 section"),
|
||||
)
|
||||
yield Completion(
|
||||
"item",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet="item {\n $0\n}",
|
||||
sort_text=get_sort_key(CompletionPriority.CLASS, "1 item"),
|
||||
)
|
||||
yield Completion("item", CompletionItemKind.Snippet, snippet="item {\n $0\n}")
|
||||
yield Completion(
|
||||
"item (shorthand)",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet='item (_("${1:Label}"), "${2:action-name}", "${3:icon-name}")',
|
||||
sort_text=get_sort_key(CompletionPriority.CLASS, "0 item (shorthand)"),
|
||||
)
|
||||
|
||||
yield Completion("label", CompletionItemKind.Snippet, snippet="label: $0;")
|
||||
yield Completion("action", CompletionItemKind.Snippet, snippet='action: "$0";')
|
||||
yield Completion("icon", CompletionItemKind.Snippet, snippet='icon: "$0";')
|
||||
yield Completion(
|
||||
"label",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet="label: $0;",
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "label"),
|
||||
)
|
||||
yield Completion(
|
||||
"action",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet='action: "$0";',
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "action"),
|
||||
)
|
||||
yield Completion(
|
||||
"icon",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet='icon: "$0";',
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "icon"),
|
||||
)
|
||||
|
||||
|
||||
@decompiler("menu")
|
||||
|
|
|
@ -23,22 +23,20 @@ from .values import StringValue
|
|||
|
||||
|
||||
class ExtScaleMark(AstNode):
|
||||
grammar = [
|
||||
grammar = Statement(
|
||||
Keyword("mark"),
|
||||
Match("(").expected(),
|
||||
[
|
||||
Optional(AnyOf(UseExact("sign", "-"), UseExact("sign", "+"))),
|
||||
UseNumber("value"),
|
||||
Optional(
|
||||
[
|
||||
",",
|
||||
UseIdent("position"),
|
||||
Optional([",", StringValue]),
|
||||
]
|
||||
),
|
||||
],
|
||||
Match(")").expected(),
|
||||
]
|
||||
Optional(AnyOf(UseExact("sign", "-"), UseExact("sign", "+"))),
|
||||
UseNumber("value").expected("value"),
|
||||
Optional(
|
||||
[
|
||||
",",
|
||||
UseIdent("position").expected("position"),
|
||||
Optional([",", to_parse_node(StringValue).expected("label")]),
|
||||
]
|
||||
),
|
||||
end=")",
|
||||
)
|
||||
|
||||
@property
|
||||
def value(self) -> float:
|
||||
|
@ -134,20 +132,42 @@ class ExtScaleMarks(AstNode):
|
|||
|
||||
@completer(
|
||||
applies_in=[ObjectContent],
|
||||
applies_in_subclass=("Gtk", "Scale"),
|
||||
applies_in_subclass=[("Gtk", "Scale")],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def complete_marks(lsp, ast_node, match_variables):
|
||||
yield Completion("marks", CompletionItemKind.Keyword, snippet="marks [\n\t$0\n]")
|
||||
def complete_marks(_ctx: CompletionContext):
|
||||
yield Completion(
|
||||
"marks",
|
||||
CompletionItemKind.Keyword,
|
||||
snippet="marks [\n\t$0\n]",
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "marks"),
|
||||
)
|
||||
|
||||
|
||||
@completer(
|
||||
applies_in=[ExtScaleMarks],
|
||||
)
|
||||
def complete_mark(lsp, ast_node, match_variables):
|
||||
def complete_mark(_ctx: CompletionContext):
|
||||
yield Completion("mark", CompletionItemKind.Keyword, snippet="mark ($0),")
|
||||
|
||||
|
||||
@completer(
|
||||
applies_in=[ExtScaleMark],
|
||||
matches=[[(TokenType.NUMBER, None), (TokenType.PUNCTUATION, ",")]],
|
||||
)
|
||||
def complete_mark_position(ctx: CompletionContext):
|
||||
gir = ctx.ast_node.root.gir
|
||||
response_type = gir.get_type("PositionType", "Gtk")
|
||||
yield from [
|
||||
Completion(
|
||||
name,
|
||||
kind=CompletionItemKind.EnumMember,
|
||||
docs=member.doc,
|
||||
)
|
||||
for name, member in response_type.members.items()
|
||||
]
|
||||
|
||||
|
||||
@decompiler("marks")
|
||||
def decompile_marks(
|
||||
ctx,
|
||||
|
|
|
@ -101,11 +101,16 @@ class ExtSizeGroupWidgets(AstNode):
|
|||
|
||||
@completer(
|
||||
applies_in=[ObjectContent],
|
||||
applies_in_subclass=("Gtk", "SizeGroup"),
|
||||
applies_in_subclass=[("Gtk", "SizeGroup")],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def size_group_completer(lsp, ast_node, match_variables):
|
||||
yield Completion("widgets", CompletionItemKind.Snippet, snippet="widgets [$0]")
|
||||
def size_group_completer(_ctx: CompletionContext):
|
||||
yield Completion(
|
||||
"widgets",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet="widgets [$0]",
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "widgets"),
|
||||
)
|
||||
|
||||
|
||||
@decompiler("widgets")
|
||||
|
|
|
@ -72,11 +72,16 @@ class ExtStringListStrings(AstNode):
|
|||
|
||||
@completer(
|
||||
applies_in=[ObjectContent],
|
||||
applies_in_subclass=("Gtk", "StringList"),
|
||||
applies_in_subclass=[("Gtk", "StringList")],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def strings_completer(lsp, ast_node, match_variables):
|
||||
yield Completion("strings", CompletionItemKind.Snippet, snippet="strings [$0]")
|
||||
def strings_completer(_ctx: CompletionContext):
|
||||
yield Completion(
|
||||
"strings",
|
||||
CompletionItemKind.Snippet,
|
||||
snippet="strings [$0]",
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "strings"),
|
||||
)
|
||||
|
||||
|
||||
@decompiler("items", parent_type="Gtk.StringList")
|
||||
|
|
|
@ -77,11 +77,16 @@ class ExtStyles(AstNode):
|
|||
|
||||
@completer(
|
||||
applies_in=[ObjectContent],
|
||||
applies_in_subclass=("Gtk", "Widget"),
|
||||
applies_in_subclass=[("Gtk", "Widget")],
|
||||
matches=new_statement_patterns,
|
||||
)
|
||||
def style_completer(lsp, ast_node, match_variables):
|
||||
yield Completion("styles", CompletionItemKind.Keyword, snippet='styles ["$0"]')
|
||||
def style_completer(_ctx: CompletionContext):
|
||||
yield Completion(
|
||||
"styles",
|
||||
CompletionItemKind.Keyword,
|
||||
snippet='styles ["$0"]',
|
||||
sort_text=get_sort_key(CompletionPriority.OBJECT_MEMBER, "styles"),
|
||||
)
|
||||
|
||||
|
||||
@decompiler("style")
|
||||
|
|
|
@ -31,7 +31,12 @@ ALLOWED_PARENTS: T.List[T.Tuple[str, str]] = [
|
|||
|
||||
|
||||
class ChildInternal(AstNode):
|
||||
grammar = ["internal-child", UseIdent("internal_child")]
|
||||
grammar = [
|
||||
"[",
|
||||
"internal-child",
|
||||
UseIdent("internal_child").expected("internal child name"),
|
||||
Match("]").expected(),
|
||||
]
|
||||
|
||||
@property
|
||||
def internal_child(self) -> str:
|
||||
|
@ -39,7 +44,7 @@ class ChildInternal(AstNode):
|
|||
|
||||
|
||||
class ChildType(AstNode):
|
||||
grammar = UseIdent("child_type").expected("a child type")
|
||||
grammar = ["[", UseIdent("child_type").expected("a child type"), "]"]
|
||||
|
||||
@property
|
||||
def child_type(self) -> str:
|
||||
|
@ -59,7 +64,7 @@ class ChildExtension(AstNode):
|
|||
|
||||
|
||||
class ChildAnnotation(AstNode):
|
||||
grammar = ["[", AnyOf(ChildInternal, ChildExtension, ChildType), "]"]
|
||||
grammar = AnyOf(ChildInternal, ChildExtension, ChildType)
|
||||
|
||||
@property
|
||||
def child(self) -> T.Union[ChildInternal, ChildExtension, ChildType]:
|
||||
|
|
|
@ -28,19 +28,21 @@ class ExtResponse(AstNode):
|
|||
|
||||
ALLOWED_PARENTS: T.List[T.Tuple[str, str]] = [("Gtk", "Dialog"), ("Gtk", "InfoBar")]
|
||||
|
||||
grammar = [
|
||||
grammar = Statement(
|
||||
"[",
|
||||
Keyword("action"),
|
||||
Keyword("response"),
|
||||
"=",
|
||||
Match("=").expected(),
|
||||
AnyOf(
|
||||
UseIdent("response_id"),
|
||||
[
|
||||
Optional(UseExact("sign", "-")),
|
||||
UseNumber("response_id"),
|
||||
],
|
||||
),
|
||||
).expected("response ID"),
|
||||
Optional([Keyword("default"), UseLiteral("is_default", True)]),
|
||||
]
|
||||
end="]",
|
||||
)
|
||||
|
||||
@validate()
|
||||
def parent_has_action_widgets(self) -> None:
|
||||
|
|
|
@ -27,11 +27,11 @@ class TypeName(AstNode):
|
|||
[
|
||||
UseIdent("namespace"),
|
||||
".",
|
||||
UseIdent("class_name"),
|
||||
UseIdent("class_name").expected("class name"),
|
||||
],
|
||||
[
|
||||
AnyOf("$", [".", UseLiteral("old_extern", True)]),
|
||||
UseIdent("class_name"),
|
||||
UseIdent("class_name").expected("class name"),
|
||||
UseLiteral("extern", True),
|
||||
],
|
||||
UseIdent("class_name"),
|
||||
|
@ -47,7 +47,11 @@ class TypeName(AstNode):
|
|||
|
||||
@validate("class_name")
|
||||
def type_exists(self):
|
||||
if not self.tokens["extern"] and self.gir_ns is not None:
|
||||
if (
|
||||
not self.tokens["extern"]
|
||||
and self.gir_ns is not None
|
||||
and self.tokens["class_name"] is not None
|
||||
):
|
||||
self.root.gir.validate_type(
|
||||
self.tokens["class_name"], self.tokens["namespace"]
|
||||
)
|
||||
|
@ -182,3 +186,14 @@ class TemplateClassName(ClassName):
|
|||
self.root.gir.validate_type(
|
||||
self.tokens["class_name"], self.tokens["namespace"]
|
||||
)
|
||||
|
||||
|
||||
class BracketedTypeName(AstNode):
|
||||
grammar = Statement("<", to_parse_node(TypeName).expected("type name"), end=">")
|
||||
|
||||
@property
|
||||
def type_name(self) -> T.Optional[TypeName]:
|
||||
if len(self.children[TypeName]) == 0:
|
||||
return None
|
||||
|
||||
return self.children[TypeName][0]
|
||||
|
|
|
@ -110,16 +110,22 @@ class UI(AstNode):
|
|||
and self.template.class_name.glib_type_name == id
|
||||
)
|
||||
|
||||
def import_code_action(self, ns: str, version: str) -> CodeAction:
|
||||
if len(self.children[Import]):
|
||||
pos = self.children[Import][-1].range.end
|
||||
else:
|
||||
pos = self.children[GtkDirective][0].range.end
|
||||
def import_range(self, ns: str):
|
||||
"""Returns a range to insert a new import statement"""
|
||||
pos = self.children[GtkDirective][0].range.end
|
||||
|
||||
# try to insert alphabetically
|
||||
for import_ in self.children[Import]:
|
||||
if ns.lower() > import_.namespace.lower():
|
||||
pos = import_.range.end
|
||||
|
||||
return Range(pos, pos, self.group.text)
|
||||
|
||||
def import_code_action(self, ns: str, version: str) -> CodeAction:
|
||||
return CodeAction(
|
||||
f"Import {ns} {version}",
|
||||
f"\nusing {ns} {version};",
|
||||
Range(pos, pos, self.group.text),
|
||||
self.import_range(ns),
|
||||
)
|
||||
|
||||
@cached_property
|
||||
|
|
|
@ -26,7 +26,7 @@ from .common import *
|
|||
from .contexts import ExprValueCtx, ScopeCtx, ValueTypeCtx
|
||||
from .expression import Expression
|
||||
from .gobject_object import Object
|
||||
from .types import TypeName
|
||||
from .types import BracketedTypeName, TypeName
|
||||
|
||||
|
||||
class Translated(AstNode):
|
||||
|
@ -80,11 +80,7 @@ class TypeLiteral(AstNode):
|
|||
grammar = [
|
||||
"typeof",
|
||||
AnyOf(
|
||||
[
|
||||
"<",
|
||||
to_parse_node(TypeName).expected("type name"),
|
||||
Match(">").expected(),
|
||||
],
|
||||
BracketedTypeName,
|
||||
[
|
||||
UseExact("lparen", "("),
|
||||
to_parse_node(TypeName).expected("type name"),
|
||||
|
@ -98,8 +94,13 @@ class TypeLiteral(AstNode):
|
|||
return gir.TypeType()
|
||||
|
||||
@property
|
||||
def type_name(self) -> TypeName:
|
||||
return self.children[TypeName][0]
|
||||
def type_name(self) -> T.Optional[TypeName]:
|
||||
if len(self.children[BracketedTypeName]) == 1:
|
||||
return self.children[BracketedTypeName][0].type_name
|
||||
elif len(self.children[TypeName]) == 1:
|
||||
return self.children[TypeName][0]
|
||||
else:
|
||||
return None
|
||||
|
||||
@validate()
|
||||
def validate_for_type(self) -> None:
|
||||
|
@ -338,7 +339,14 @@ class IdentLiteral(AstNode):
|
|||
raise CompileError(
|
||||
'"item" can only be used in an expression literal'
|
||||
)
|
||||
elif self.ident not in ["true", "false"]:
|
||||
elif self.ident in ["true", "false"]:
|
||||
if expected_type is not None and not isinstance(
|
||||
expected_type, gir.BoolType
|
||||
):
|
||||
raise CompileError(
|
||||
f"Cannot assign boolean to {expected_type.full_name}"
|
||||
)
|
||||
else:
|
||||
raise CompileError(
|
||||
f"Could not find object with ID {self.ident}",
|
||||
did_you_mean=(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue