mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
lsp: Fix completions when editing existing item
Many completion snippets insert more than just the name. For example, the object completer inserts the braces and places your cursor inside them automatically, to save some typing. However, if you're changing the class of an existing object, this isn't what you want. Changed so that if the next token is '{', only the name is inserted. Made similar changes to the property and signal completers.
This commit is contained in:
parent
2e42dc6848
commit
bf4d8579b6
13 changed files with 122 additions and 97 deletions
|
@ -31,13 +31,18 @@ Pattern = T.List[T.Tuple[TokenType, T.Optional[str]]]
|
||||||
|
|
||||||
|
|
||||||
def _complete(
|
def _complete(
|
||||||
lsp, ast_node: AstNode, tokens: T.List[Token], idx: int, token_idx: int
|
lsp,
|
||||||
|
ast_node: AstNode,
|
||||||
|
tokens: T.List[Token],
|
||||||
|
idx: int,
|
||||||
|
token_idx: int,
|
||||||
|
next_token: Token,
|
||||||
) -> T.Iterator[Completion]:
|
) -> T.Iterator[Completion]:
|
||||||
for child in ast_node.children:
|
for child in ast_node.children:
|
||||||
if child.group.start <= idx and (
|
if child.group.start <= idx and (
|
||||||
idx < child.group.end or (idx == child.group.end and child.incomplete)
|
idx < child.group.end or (idx == child.group.end and child.incomplete)
|
||||||
):
|
):
|
||||||
yield from _complete(lsp, child, tokens, idx, token_idx)
|
yield from _complete(lsp, child, tokens, idx, token_idx, next_token)
|
||||||
return
|
return
|
||||||
|
|
||||||
prev_tokens: T.List[Token] = []
|
prev_tokens: T.List[Token] = []
|
||||||
|
@ -50,7 +55,7 @@ def _complete(
|
||||||
token_idx -= 1
|
token_idx -= 1
|
||||||
|
|
||||||
for completer in ast_node.completers:
|
for completer in ast_node.completers:
|
||||||
yield from completer(prev_tokens, ast_node, lsp)
|
yield from completer(prev_tokens, next_token, ast_node, lsp)
|
||||||
|
|
||||||
|
|
||||||
def complete(
|
def complete(
|
||||||
|
@ -62,16 +67,24 @@ def complete(
|
||||||
if token.start < idx <= token.end:
|
if token.start < idx <= token.end:
|
||||||
token_idx = i
|
token_idx = i
|
||||||
|
|
||||||
|
if tokens[token_idx].type == TokenType.EOF:
|
||||||
|
next_token = tokens[token_idx]
|
||||||
|
else:
|
||||||
|
next_token_idx = token_idx + 1
|
||||||
|
while tokens[next_token_idx].type == TokenType.WHITESPACE:
|
||||||
|
next_token_idx += 1
|
||||||
|
next_token = tokens[next_token_idx]
|
||||||
|
|
||||||
# if the current token is an identifier or whitespace, move to the token before it
|
# if the current token is an identifier or whitespace, move to the token before it
|
||||||
while tokens[token_idx].type in [TokenType.IDENT, TokenType.WHITESPACE]:
|
while tokens[token_idx].type in [TokenType.IDENT, TokenType.WHITESPACE]:
|
||||||
idx = tokens[token_idx].start
|
idx = tokens[token_idx].start
|
||||||
token_idx -= 1
|
token_idx -= 1
|
||||||
|
|
||||||
yield from _complete(lsp, ast_node, tokens, idx, token_idx)
|
yield from _complete(lsp, ast_node, tokens, idx, token_idx, next_token)
|
||||||
|
|
||||||
|
|
||||||
@completer([language.GtkDirective])
|
@completer([language.GtkDirective])
|
||||||
def using_gtk(lsp, ast_node, match_variables):
|
def using_gtk(_ctx: CompletionContext):
|
||||||
yield Completion(
|
yield Completion(
|
||||||
"using Gtk 4.0", CompletionItemKind.Keyword, snippet="using Gtk 4.0;\n"
|
"using Gtk 4.0", CompletionItemKind.Keyword, snippet="using Gtk 4.0;\n"
|
||||||
)
|
)
|
||||||
|
@ -81,9 +94,9 @@ def using_gtk(lsp, ast_node, match_variables):
|
||||||
applies_in=[language.UI, language.ObjectContent, language.Template],
|
applies_in=[language.UI, language.ObjectContent, language.Template],
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def namespace(lsp, ast_node, match_variables):
|
def namespace(ctx: CompletionContext):
|
||||||
yield Completion("Gtk", CompletionItemKind.Module, text="Gtk.")
|
yield Completion("Gtk", CompletionItemKind.Module, text="Gtk.")
|
||||||
for ns in ast_node.root.children[language.Import]:
|
for ns in ctx.ast_node.root.children[language.Import]:
|
||||||
if ns.gir_namespace is not None:
|
if ns.gir_namespace is not None:
|
||||||
yield Completion(
|
yield Completion(
|
||||||
ns.gir_namespace.name,
|
ns.gir_namespace.name,
|
||||||
|
@ -99,14 +112,18 @@ def namespace(lsp, ast_node, match_variables):
|
||||||
[(TokenType.IDENT, None), (TokenType.OP, ".")],
|
[(TokenType.IDENT, None), (TokenType.OP, ".")],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def object_completer(lsp, ast_node, match_variables):
|
def object_completer(ctx: CompletionContext):
|
||||||
ns = ast_node.root.gir.namespaces.get(match_variables[0])
|
ns = ctx.ast_node.root.gir.namespaces.get(ctx.match_variables[0])
|
||||||
if ns is not None:
|
if ns is not None:
|
||||||
for c in ns.classes.values():
|
for c in ns.classes.values():
|
||||||
|
snippet = c.name
|
||||||
|
if str(ctx.next_token) != "{":
|
||||||
|
snippet += " {\n $0\n}"
|
||||||
|
|
||||||
yield Completion(
|
yield Completion(
|
||||||
c.name,
|
c.name,
|
||||||
CompletionItemKind.Class,
|
CompletionItemKind.Class,
|
||||||
snippet=f"{c.name} {{\n $0\n}}",
|
snippet=snippet,
|
||||||
docs=c.doc,
|
docs=c.doc,
|
||||||
detail=c.detail,
|
detail=c.detail,
|
||||||
)
|
)
|
||||||
|
@ -116,14 +133,18 @@ def object_completer(lsp, ast_node, match_variables):
|
||||||
applies_in=[language.UI, language.ObjectContent, language.Template],
|
applies_in=[language.UI, language.ObjectContent, language.Template],
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def gtk_object_completer(lsp, ast_node, match_variables):
|
def gtk_object_completer(ctx: CompletionContext):
|
||||||
ns = ast_node.root.gir.namespaces.get("Gtk")
|
ns = ctx.ast_node.root.gir.namespaces.get("Gtk")
|
||||||
if ns is not None:
|
if ns is not None:
|
||||||
for c in ns.classes.values():
|
for c in ns.classes.values():
|
||||||
|
snippet = c.name
|
||||||
|
if str(ctx.next_token) != "{":
|
||||||
|
snippet += " {\n $0\n}"
|
||||||
|
|
||||||
yield Completion(
|
yield Completion(
|
||||||
c.name,
|
c.name,
|
||||||
CompletionItemKind.Class,
|
CompletionItemKind.Class,
|
||||||
snippet=f"{c.name} {{\n $0\n}}",
|
snippet=snippet,
|
||||||
docs=c.doc,
|
docs=c.doc,
|
||||||
detail=c.detail,
|
detail=c.detail,
|
||||||
)
|
)
|
||||||
|
@ -133,27 +154,34 @@ def gtk_object_completer(lsp, ast_node, match_variables):
|
||||||
applies_in=[language.ObjectContent],
|
applies_in=[language.ObjectContent],
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def property_completer(lsp, ast_node, match_variables):
|
def property_completer(ctx: CompletionContext):
|
||||||
if ast_node.gir_class and hasattr(ast_node.gir_class, "properties"):
|
assert isinstance(ctx.ast_node, language.ObjectContent)
|
||||||
for prop_name, prop in ast_node.gir_class.properties.items():
|
if ctx.ast_node.gir_class and hasattr(ctx.ast_node.gir_class, "properties"):
|
||||||
if (
|
for prop_name, prop in ctx.ast_node.gir_class.properties.items():
|
||||||
|
if str(ctx.next_token) == ":":
|
||||||
|
snippet = prop_name
|
||||||
|
elif (
|
||||||
isinstance(prop.type, gir.BoolType)
|
isinstance(prop.type, gir.BoolType)
|
||||||
and lsp.client_supports_completion_choice
|
and ctx.client_supports_completion_choice
|
||||||
):
|
):
|
||||||
yield Completion(
|
snippet = f"{prop_name}: ${{1|true,false|}};"
|
||||||
prop_name,
|
|
||||||
CompletionItemKind.Property,
|
|
||||||
sort_text=f"0 {prop_name}",
|
|
||||||
snippet=f"{prop_name}: ${{1|true,false|}};",
|
|
||||||
docs=prop.doc,
|
|
||||||
detail=prop.detail,
|
|
||||||
)
|
|
||||||
elif isinstance(prop.type, gir.StringType):
|
elif isinstance(prop.type, gir.StringType):
|
||||||
snippet = (
|
snippet = (
|
||||||
f'{prop_name}: _("$0");'
|
f'{prop_name}: _("$0");'
|
||||||
if annotations.is_property_translated(prop)
|
if annotations.is_property_translated(prop)
|
||||||
else f'{prop_name}: "$0";'
|
else f'{prop_name}: "$0";'
|
||||||
)
|
)
|
||||||
|
elif (
|
||||||
|
isinstance(prop.type, gir.Enumeration)
|
||||||
|
and len(prop.type.members) <= 10
|
||||||
|
and ctx.client_supports_completion_choice
|
||||||
|
):
|
||||||
|
choices = ",".join(prop.type.members.keys())
|
||||||
|
snippet = f"{prop_name}: ${{1|{choices}|}};"
|
||||||
|
elif prop.type.full_name == "Gtk.Expression":
|
||||||
|
snippet = f"{prop_name}: expr $0;"
|
||||||
|
else:
|
||||||
|
snippet = f"{prop_name}: $0;"
|
||||||
|
|
||||||
yield Completion(
|
yield Completion(
|
||||||
prop_name,
|
prop_name,
|
||||||
|
@ -163,46 +191,18 @@ def property_completer(lsp, ast_node, match_variables):
|
||||||
docs=prop.doc,
|
docs=prop.doc,
|
||||||
detail=prop.detail,
|
detail=prop.detail,
|
||||||
)
|
)
|
||||||
elif (
|
|
||||||
isinstance(prop.type, gir.Enumeration)
|
|
||||||
and len(prop.type.members) <= 10
|
|
||||||
and lsp.client_supports_completion_choice
|
|
||||||
):
|
|
||||||
choices = ",".join(prop.type.members.keys())
|
|
||||||
yield Completion(
|
|
||||||
prop_name,
|
|
||||||
CompletionItemKind.Property,
|
|
||||||
sort_text=f"0 {prop_name}",
|
|
||||||
snippet=f"{prop_name}: ${{1|{choices}|}};",
|
|
||||||
docs=prop.doc,
|
|
||||||
detail=prop.detail,
|
|
||||||
)
|
|
||||||
elif prop.type.full_name == "Gtk.Expression":
|
|
||||||
yield Completion(
|
|
||||||
prop_name,
|
|
||||||
CompletionItemKind.Property,
|
|
||||||
sort_text=f"0 {prop_name}",
|
|
||||||
snippet=f"{prop_name}: expr $0;",
|
|
||||||
docs=prop.doc,
|
|
||||||
detail=prop.detail,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
yield Completion(
|
|
||||||
prop_name,
|
|
||||||
CompletionItemKind.Property,
|
|
||||||
sort_text=f"0 {prop_name}",
|
|
||||||
snippet=f"{prop_name}: $0;",
|
|
||||||
docs=prop.doc,
|
|
||||||
detail=prop.detail,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@completer(
|
@completer(
|
||||||
applies_in=[language.Property, language.A11yProperty],
|
applies_in=[language.Property, language.A11yProperty],
|
||||||
matches=[[(TokenType.IDENT, None), (TokenType.OP, ":")]],
|
matches=[[(TokenType.IDENT, None), (TokenType.OP, ":")]],
|
||||||
)
|
)
|
||||||
def prop_value_completer(lsp, ast_node, match_variables):
|
def prop_value_completer(ctx: CompletionContext):
|
||||||
if (vt := ast_node.value_type) is not None:
|
assert isinstance(ctx.ast_node, language.Property) or isinstance(
|
||||||
|
ctx.ast_node, language.A11yProperty
|
||||||
|
)
|
||||||
|
|
||||||
|
if (vt := ctx.ast_node.value_type) is not None:
|
||||||
if isinstance(vt.value_type, gir.Enumeration):
|
if isinstance(vt.value_type, gir.Enumeration):
|
||||||
for name, member in vt.value_type.members.items():
|
for name, member in vt.value_type.members.items():
|
||||||
yield Completion(
|
yield Completion(
|
||||||
|
@ -221,30 +221,38 @@ def prop_value_completer(lsp, ast_node, match_variables):
|
||||||
applies_in=[language.ObjectContent],
|
applies_in=[language.ObjectContent],
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def signal_completer(lsp, ast_node, match_variables):
|
def signal_completer(ctx: CompletionContext):
|
||||||
if ast_node.gir_class and hasattr(ast_node.gir_class, "signals"):
|
assert isinstance(ctx.ast_node, language.ObjectContent)
|
||||||
for signal_name, signal in ast_node.gir_class.signals.items():
|
|
||||||
if not isinstance(ast_node.parent, language.Object):
|
if ctx.ast_node.gir_class and hasattr(ctx.ast_node.gir_class, "signals"):
|
||||||
|
for signal_name, signal in ctx.ast_node.gir_class.signals.items():
|
||||||
|
if str(ctx.next_token) == "=>":
|
||||||
|
snippet = signal_name
|
||||||
|
else:
|
||||||
|
if not isinstance(ctx.ast_node.parent, language.Object):
|
||||||
name = "on"
|
name = "on"
|
||||||
else:
|
else:
|
||||||
name = "on_" + (
|
name = "on_" + (
|
||||||
ast_node.parent.children[ClassName][0].tokens["id"]
|
ctx.ast_node.parent.children[ClassName][0].tokens["id"]
|
||||||
or ast_node.parent.children[ClassName][0]
|
or ctx.ast_node.parent.children[ClassName][0]
|
||||||
.tokens["class_name"]
|
.tokens["class_name"]
|
||||||
.lower()
|
.lower()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
snippet = f"{signal_name} => \\$${{1:${name}_{signal_name.replace('-', '_')}}}()$0;"
|
||||||
|
|
||||||
yield Completion(
|
yield Completion(
|
||||||
signal_name,
|
signal_name,
|
||||||
CompletionItemKind.Event,
|
CompletionItemKind.Event,
|
||||||
sort_text=f"1 {signal_name}",
|
sort_text=f"1 {signal_name}",
|
||||||
snippet=f"{signal_name} => \\$${{1:${name}_{signal_name.replace('-', '_')}}}()$0;",
|
snippet=snippet,
|
||||||
docs=signal.doc,
|
docs=signal.doc,
|
||||||
detail=signal.detail,
|
detail=signal.detail,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@completer(applies_in=[language.UI], matches=new_statement_patterns)
|
@completer(applies_in=[language.UI], matches=new_statement_patterns)
|
||||||
def template_completer(lsp, ast_node, match_variables):
|
def template_completer(_ctx: CompletionContext):
|
||||||
yield Completion(
|
yield Completion(
|
||||||
"template",
|
"template",
|
||||||
CompletionItemKind.Snippet,
|
CompletionItemKind.Snippet,
|
||||||
|
|
|
@ -19,10 +19,21 @@
|
||||||
|
|
||||||
|
|
||||||
import typing as T
|
import typing as T
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from .ast_utils import AstNode
|
||||||
from .lsp_utils import Completion
|
from .lsp_utils import Completion
|
||||||
from .tokenizer import Token, TokenType
|
from .tokenizer import Token, TokenType
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CompletionContext:
|
||||||
|
client_supports_completion_choice: bool
|
||||||
|
ast_node: AstNode
|
||||||
|
match_variables: T.List[str]
|
||||||
|
next_token: Token
|
||||||
|
|
||||||
|
|
||||||
new_statement_patterns = [
|
new_statement_patterns = [
|
||||||
[(TokenType.PUNCTUATION, "{")],
|
[(TokenType.PUNCTUATION, "{")],
|
||||||
[(TokenType.PUNCTUATION, "}")],
|
[(TokenType.PUNCTUATION, "}")],
|
||||||
|
@ -32,8 +43,8 @@ new_statement_patterns = [
|
||||||
|
|
||||||
|
|
||||||
def completer(applies_in: T.List, matches: T.List = [], applies_in_subclass=None):
|
def completer(applies_in: T.List, matches: T.List = [], applies_in_subclass=None):
|
||||||
def decorator(func):
|
def decorator(func: T.Callable[[CompletionContext], T.Generator[Completion]]):
|
||||||
def inner(prev_tokens: T.List[Token], ast_node, lsp):
|
def inner(prev_tokens: T.List[Token], next_token: Token, ast_node, lsp):
|
||||||
# For completers that apply in ObjectContent nodes, we can further
|
# For completers that apply in ObjectContent nodes, we can further
|
||||||
# check that the object is the right class
|
# check that the object is the right class
|
||||||
if applies_in_subclass is not None:
|
if applies_in_subclass is not None:
|
||||||
|
@ -66,7 +77,13 @@ def completer(applies_in: T.List, matches: T.List = [], applies_in_subclass=None
|
||||||
if not any_match:
|
if not any_match:
|
||||||
return
|
return
|
||||||
|
|
||||||
yield from func(lsp, ast_node, match_variables)
|
context = CompletionContext(
|
||||||
|
client_supports_completion_choice=lsp.client_supports_completion_choice,
|
||||||
|
ast_node=ast_node,
|
||||||
|
match_variables=match_variables,
|
||||||
|
next_token=next_token,
|
||||||
|
)
|
||||||
|
yield from func(context)
|
||||||
|
|
||||||
for c in applies_in:
|
for c in applies_in:
|
||||||
c.completers.append(inner)
|
c.completers.append(inner)
|
||||||
|
|
|
@ -143,7 +143,7 @@ class ExtAdwResponseDialog(AstNode):
|
||||||
applies_in_subclass=("Adw", "MessageDialog"),
|
applies_in_subclass=("Adw", "MessageDialog"),
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def complete_adw_message_dialog(lsp, ast_node, match_variables):
|
def complete_adw_message_dialog(_ctx: CompletionContext):
|
||||||
yield Completion(
|
yield Completion(
|
||||||
"responses", CompletionItemKind.Keyword, snippet="responses [\n\t$0\n]"
|
"responses", CompletionItemKind.Keyword, snippet="responses [\n\t$0\n]"
|
||||||
)
|
)
|
||||||
|
@ -154,7 +154,7 @@ def complete_adw_message_dialog(lsp, ast_node, match_variables):
|
||||||
applies_in_subclass=("Adw", "AlertDialog"),
|
applies_in_subclass=("Adw", "AlertDialog"),
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def complete_adw_alert_dialog(lsp, ast_node, match_variables):
|
def complete_adw_alert_dialog(_ctx: CompletionContext):
|
||||||
yield Completion(
|
yield Completion(
|
||||||
"responses", CompletionItemKind.Keyword, snippet="responses [\n\t$0\n]"
|
"responses", CompletionItemKind.Keyword, snippet="responses [\n\t$0\n]"
|
||||||
)
|
)
|
||||||
|
|
|
@ -232,7 +232,7 @@ class ExtAccessibility(AstNode):
|
||||||
applies_in=[ObjectContent],
|
applies_in=[ObjectContent],
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def a11y_completer(lsp, ast_node, match_variables):
|
def a11y_completer(_ctx: CompletionContext):
|
||||||
yield Completion(
|
yield Completion(
|
||||||
"accessibility", CompletionItemKind.Snippet, snippet="accessibility {\n $0\n}"
|
"accessibility", CompletionItemKind.Snippet, snippet="accessibility {\n $0\n}"
|
||||||
)
|
)
|
||||||
|
@ -242,12 +242,12 @@ def a11y_completer(lsp, ast_node, match_variables):
|
||||||
applies_in=[ExtAccessibility],
|
applies_in=[ExtAccessibility],
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def a11y_name_completer(lsp, ast_node, match_variables):
|
def a11y_name_completer(ctx: CompletionContext):
|
||||||
for name, type in get_types(ast_node.root.gir).items():
|
for name, type in get_types(ctx.ast_node.root.gir).items():
|
||||||
yield Completion(
|
yield Completion(
|
||||||
name,
|
name,
|
||||||
CompletionItemKind.Property,
|
CompletionItemKind.Property,
|
||||||
docs=_get_docs(ast_node.root.gir, type.name),
|
docs=_get_docs(ctx.ast_node.root.gir, type.name),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ class ExtComboBoxItems(AstNode):
|
||||||
applies_in_subclass=("Gtk", "ComboBoxText"),
|
applies_in_subclass=("Gtk", "ComboBoxText"),
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def items_completer(lsp, ast_node, match_variables):
|
def items_completer(_ctx: CompletionContext):
|
||||||
yield Completion("items", CompletionItemKind.Snippet, snippet="items [$0]")
|
yield Completion("items", CompletionItemKind.Snippet, snippet="items [$0]")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ ext_file_filter_suffixes = create_node("suffixes", "suffix")
|
||||||
applies_in_subclass=("Gtk", "FileFilter"),
|
applies_in_subclass=("Gtk", "FileFilter"),
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def file_filter_completer(lsp, ast_node, match_variables):
|
def file_filter_completer(_ctx: CompletionContext):
|
||||||
yield Completion(
|
yield Completion(
|
||||||
"mime-types", CompletionItemKind.Snippet, snippet='mime-types ["$0"]'
|
"mime-types", CompletionItemKind.Snippet, snippet='mime-types ["$0"]'
|
||||||
)
|
)
|
||||||
|
|
|
@ -93,7 +93,7 @@ class ExtLayout(AstNode):
|
||||||
applies_in_subclass=("Gtk", "Widget"),
|
applies_in_subclass=("Gtk", "Widget"),
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def layout_completer(lsp, ast_node, match_variables):
|
def layout_completer(_ctx: CompletionContext):
|
||||||
yield Completion("layout", CompletionItemKind.Snippet, snippet="layout {\n $0\n}")
|
yield Completion("layout", CompletionItemKind.Snippet, snippet="layout {\n $0\n}")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -243,7 +243,7 @@ from .ui import UI
|
||||||
applies_in=[UI],
|
applies_in=[UI],
|
||||||
matches=new_statement_patterns,
|
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}")
|
yield Completion("menu", CompletionItemKind.Snippet, snippet="menu {\n $0\n}")
|
||||||
|
|
||||||
|
|
||||||
|
@ -251,7 +251,7 @@ def menu_completer(lsp, ast_node, match_variables):
|
||||||
applies_in=[Menu],
|
applies_in=[Menu],
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def menu_content_completer(lsp, ast_node, match_variables):
|
def menu_content_completer(_ctx: CompletionContext):
|
||||||
yield Completion(
|
yield Completion(
|
||||||
"submenu", CompletionItemKind.Snippet, snippet="submenu {\n $0\n}"
|
"submenu", CompletionItemKind.Snippet, snippet="submenu {\n $0\n}"
|
||||||
)
|
)
|
||||||
|
|
|
@ -137,14 +137,14 @@ class ExtScaleMarks(AstNode):
|
||||||
applies_in_subclass=("Gtk", "Scale"),
|
applies_in_subclass=("Gtk", "Scale"),
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def complete_marks(lsp, ast_node, match_variables):
|
def complete_marks(_ctx: CompletionContext):
|
||||||
yield Completion("marks", CompletionItemKind.Keyword, snippet="marks [\n\t$0\n]")
|
yield Completion("marks", CompletionItemKind.Keyword, snippet="marks [\n\t$0\n]")
|
||||||
|
|
||||||
|
|
||||||
@completer(
|
@completer(
|
||||||
applies_in=[ExtScaleMarks],
|
applies_in=[ExtScaleMarks],
|
||||||
)
|
)
|
||||||
def complete_mark(lsp, ast_node, match_variables):
|
def complete_mark(_ctx: CompletionContext):
|
||||||
yield Completion("mark", CompletionItemKind.Keyword, snippet="mark ($0),")
|
yield Completion("mark", CompletionItemKind.Keyword, snippet="mark ($0),")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ class ExtSizeGroupWidgets(AstNode):
|
||||||
applies_in_subclass=("Gtk", "SizeGroup"),
|
applies_in_subclass=("Gtk", "SizeGroup"),
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def size_group_completer(lsp, ast_node, match_variables):
|
def size_group_completer(_ctx: CompletionContext):
|
||||||
yield Completion("widgets", CompletionItemKind.Snippet, snippet="widgets [$0]")
|
yield Completion("widgets", CompletionItemKind.Snippet, snippet="widgets [$0]")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ class ExtStringListStrings(AstNode):
|
||||||
applies_in_subclass=("Gtk", "StringList"),
|
applies_in_subclass=("Gtk", "StringList"),
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def strings_completer(lsp, ast_node, match_variables):
|
def strings_completer(_ctx: CompletionContext):
|
||||||
yield Completion("strings", CompletionItemKind.Snippet, snippet="strings [$0]")
|
yield Completion("strings", CompletionItemKind.Snippet, snippet="strings [$0]")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ class ExtStyles(AstNode):
|
||||||
applies_in_subclass=("Gtk", "Widget"),
|
applies_in_subclass=("Gtk", "Widget"),
|
||||||
matches=new_statement_patterns,
|
matches=new_statement_patterns,
|
||||||
)
|
)
|
||||||
def style_completer(lsp, ast_node, match_variables):
|
def style_completer(_ctx: CompletionContext):
|
||||||
yield Completion("styles", CompletionItemKind.Keyword, snippet='styles ["$0"]')
|
yield Completion("styles", CompletionItemKind.Keyword, snippet='styles ["$0"]')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,11 @@ class TestSamples(unittest.TestCase):
|
||||||
|
|
||||||
def assert_ast_doesnt_crash(self, text, tokens, ast: AstNode):
|
def assert_ast_doesnt_crash(self, text, tokens, ast: AstNode):
|
||||||
lsp = LanguageServer()
|
lsp = LanguageServer()
|
||||||
for i in range(len(text)):
|
for i in range(len(text) + 1):
|
||||||
ast.get_docs(i)
|
ast.get_docs(i)
|
||||||
for i in range(len(text)):
|
for i in range(len(text) + 1):
|
||||||
list(complete(lsp, ast, tokens, i))
|
list(complete(lsp, ast, tokens, i))
|
||||||
for i in range(len(text)):
|
for i in range(len(text) + 1):
|
||||||
ast.get_reference(i)
|
ast.get_reference(i)
|
||||||
ast.get_document_symbols()
|
ast.get_document_symbols()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue