mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
lsp: Extend completion documentation
This commit is contained in:
parent
da5b9909fc
commit
a075b26769
3 changed files with 42 additions and 9 deletions
|
@ -17,6 +17,7 @@
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
import sys
|
||||||
import typing as T
|
import typing as T
|
||||||
|
|
||||||
from . import gir, language
|
from . import gir, language
|
||||||
|
@ -30,6 +31,9 @@ from .tokenizer import Token, TokenType
|
||||||
Pattern = T.List[T.Tuple[TokenType, T.Optional[str]]]
|
Pattern = T.List[T.Tuple[TokenType, T.Optional[str]]]
|
||||||
|
|
||||||
|
|
||||||
|
def debug(*args, **kwargs):
|
||||||
|
print(*args, file=sys.stderr, **kwargs)
|
||||||
|
|
||||||
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
|
||||||
) -> T.Iterator[Completion]:
|
) -> T.Iterator[Completion]:
|
||||||
|
@ -72,7 +76,9 @@ def complete(
|
||||||
|
|
||||||
@completer([language.GtkDirective])
|
@completer([language.GtkDirective])
|
||||||
def using_gtk(lsp, ast_node, match_variables):
|
def using_gtk(lsp, ast_node, match_variables):
|
||||||
yield Completion("using Gtk 4.0;", CompletionItemKind.Keyword)
|
yield Completion(
|
||||||
|
"using Gtk 4.0", CompletionItemKind.Keyword, snippet="using Gtk 4.0;\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@completer(
|
@completer(
|
||||||
|
@ -101,7 +107,7 @@ def object_completer(lsp, ast_node, match_variables):
|
||||||
ns = ast_node.root.gir.namespaces.get(match_variables[0])
|
ns = ast_node.root.gir.namespaces.get(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():
|
||||||
yield Completion(c.name, CompletionItemKind.Class, docs=c.doc)
|
yield Completion(c.name, CompletionItemKind.Class, docs=c.doc, detail=c.detail)
|
||||||
|
|
||||||
|
|
||||||
@completer(
|
@completer(
|
||||||
|
@ -112,7 +118,7 @@ def gtk_object_completer(lsp, ast_node, match_variables):
|
||||||
ns = ast_node.root.gir.namespaces.get("Gtk")
|
ns = 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():
|
||||||
yield Completion(c.name, CompletionItemKind.Class, docs=c.doc)
|
yield Completion(c.name, CompletionItemKind.Class, docs=c.doc, detail=c.detail)
|
||||||
|
|
||||||
|
|
||||||
@completer(
|
@completer(
|
||||||
|
@ -131,6 +137,8 @@ def property_completer(lsp, ast_node, match_variables):
|
||||||
CompletionItemKind.Property,
|
CompletionItemKind.Property,
|
||||||
sort_text=f"0 {prop_name}",
|
sort_text=f"0 {prop_name}",
|
||||||
snippet=f"{prop_name}: ${{1|true,false|}};",
|
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):
|
||||||
yield Completion(
|
yield Completion(
|
||||||
|
@ -138,6 +146,8 @@ def property_completer(lsp, ast_node, match_variables):
|
||||||
CompletionItemKind.Property,
|
CompletionItemKind.Property,
|
||||||
sort_text=f"0 {prop_name}",
|
sort_text=f"0 {prop_name}",
|
||||||
snippet=f'{prop_name}: "$0";',
|
snippet=f'{prop_name}: "$0";',
|
||||||
|
docs=prop.doc,
|
||||||
|
detail=prop.detail,
|
||||||
)
|
)
|
||||||
elif (
|
elif (
|
||||||
isinstance(prop.type, gir.Enumeration)
|
isinstance(prop.type, gir.Enumeration)
|
||||||
|
@ -150,6 +160,8 @@ def property_completer(lsp, ast_node, match_variables):
|
||||||
CompletionItemKind.Property,
|
CompletionItemKind.Property,
|
||||||
sort_text=f"0 {prop_name}",
|
sort_text=f"0 {prop_name}",
|
||||||
snippet=f"{prop_name}: ${{1|{choices}|}};",
|
snippet=f"{prop_name}: ${{1|{choices}|}};",
|
||||||
|
docs=prop.doc,
|
||||||
|
detail=prop.detail,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
yield Completion(
|
yield Completion(
|
||||||
|
@ -157,6 +169,8 @@ def property_completer(lsp, ast_node, match_variables):
|
||||||
CompletionItemKind.Property,
|
CompletionItemKind.Property,
|
||||||
sort_text=f"0 {prop_name}",
|
sort_text=f"0 {prop_name}",
|
||||||
snippet=f"{prop_name}: $0;",
|
snippet=f"{prop_name}: $0;",
|
||||||
|
docs=prop.doc,
|
||||||
|
detail=prop.detail,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,7 +182,12 @@ def prop_value_completer(lsp, ast_node, match_variables):
|
||||||
if (vt := ast_node.value_type) is not None:
|
if (vt := 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(name, CompletionItemKind.EnumMember, docs=member.doc)
|
yield Completion(
|
||||||
|
name,
|
||||||
|
CompletionItemKind.EnumMember,
|
||||||
|
docs=member.doc,
|
||||||
|
detail=member.detail,
|
||||||
|
)
|
||||||
|
|
||||||
elif isinstance(vt.value_type, gir.BoolType):
|
elif isinstance(vt.value_type, gir.BoolType):
|
||||||
yield Completion("true", CompletionItemKind.Constant)
|
yield Completion("true", CompletionItemKind.Constant)
|
||||||
|
@ -181,7 +200,7 @@ def prop_value_completer(lsp, ast_node, match_variables):
|
||||||
)
|
)
|
||||||
def signal_completer(lsp, ast_node, match_variables):
|
def signal_completer(lsp, ast_node, match_variables):
|
||||||
if ast_node.gir_class and not isinstance(ast_node.gir_class, gir.ExternType):
|
if ast_node.gir_class and not isinstance(ast_node.gir_class, gir.ExternType):
|
||||||
for signal in ast_node.gir_class.signals:
|
for signal_name, signal in ast_node.gir_class.signals.items():
|
||||||
if not isinstance(ast_node.parent, language.Object):
|
if not isinstance(ast_node.parent, language.Object):
|
||||||
name = "on"
|
name = "on"
|
||||||
else:
|
else:
|
||||||
|
@ -192,10 +211,12 @@ def signal_completer(lsp, ast_node, match_variables):
|
||||||
.lower()
|
.lower()
|
||||||
)
|
)
|
||||||
yield Completion(
|
yield Completion(
|
||||||
signal,
|
signal_name,
|
||||||
CompletionItemKind.Event,
|
CompletionItemKind.Event,
|
||||||
sort_text=f"1 {signal}",
|
sort_text=f"1 {signal_name}",
|
||||||
snippet=f"{signal} => \$${{1:{name}_{signal.replace('-', '_')}}}()$0;",
|
snippet=f"{signal_name} => \$${{1:{name}_{signal_name.replace('-', '_')}}}()$0;",
|
||||||
|
docs=signal.doc,
|
||||||
|
detail=signal.detail,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -336,6 +336,15 @@ class GirNode:
|
||||||
def available_in(self) -> str:
|
def available_in(self) -> str:
|
||||||
return self.xml.get("version")
|
return self.xml.get("version")
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def detail(self) -> T.Optional[str]:
|
||||||
|
try:
|
||||||
|
el = self.xml.get_elements("doc")
|
||||||
|
if len(el) == 1:
|
||||||
|
return el[0].cdata.strip().partition("\n")[0]
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def doc(self) -> T.Optional[str]:
|
def doc(self) -> T.Optional[str]:
|
||||||
sections = []
|
sections = []
|
||||||
|
|
|
@ -84,6 +84,7 @@ class Completion:
|
||||||
docs: T.Optional[str] = None
|
docs: T.Optional[str] = None
|
||||||
text: T.Optional[str] = None
|
text: T.Optional[str] = None
|
||||||
snippet: T.Optional[str] = None
|
snippet: T.Optional[str] = None
|
||||||
|
detail: T.Optional[str] = None
|
||||||
|
|
||||||
def to_json(self, snippets: bool):
|
def to_json(self, snippets: bool):
|
||||||
insert_text = self.text or self.label
|
insert_text = self.text or self.label
|
||||||
|
@ -96,7 +97,8 @@ class Completion:
|
||||||
"label": self.label,
|
"label": self.label,
|
||||||
"kind": self.kind,
|
"kind": self.kind,
|
||||||
"tags": [CompletionItemTag.Deprecated] if self.deprecated else None,
|
"tags": [CompletionItemTag.Deprecated] if self.deprecated else None,
|
||||||
"detail": self.signature,
|
# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItemLabelDetails
|
||||||
|
"labelDetails": ({"detail": self.signature} if self.signature else None),
|
||||||
"documentation": (
|
"documentation": (
|
||||||
{
|
{
|
||||||
"kind": "markdown",
|
"kind": "markdown",
|
||||||
|
@ -109,6 +111,7 @@ class Completion:
|
||||||
"sortText": self.sort_text,
|
"sortText": self.sort_text,
|
||||||
"insertText": insert_text,
|
"insertText": insert_text,
|
||||||
"insertTextFormat": insert_text_format,
|
"insertTextFormat": insert_text_format,
|
||||||
|
"detail": self.detail if self.detail else None,
|
||||||
}
|
}
|
||||||
return {k: v for k, v in result.items() if v is not None}
|
return {k: v for k, v in result.items() if v is not None}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue