mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
lsp: Add code action to add missing imports
This commit is contained in:
parent
3bcc9f4cbd
commit
35ee058192
3 changed files with 47 additions and 3 deletions
|
@ -18,7 +18,6 @@
|
||||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import typing as T
|
import typing as T
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
|
|
||||||
|
@ -29,6 +28,7 @@ from gi.repository import GIRepository # type: ignore
|
||||||
|
|
||||||
from . import typelib, xml_reader
|
from . import typelib, xml_reader
|
||||||
from .errors import CompileError, CompilerBugError
|
from .errors import CompileError, CompilerBugError
|
||||||
|
from .lsp_utils import CodeAction
|
||||||
|
|
||||||
_namespace_cache: T.Dict[str, "Namespace"] = {}
|
_namespace_cache: T.Dict[str, "Namespace"] = {}
|
||||||
_xml_cache = {}
|
_xml_cache = {}
|
||||||
|
@ -65,6 +65,27 @@ def get_namespace(namespace: str, version: str) -> "Namespace":
|
||||||
return _namespace_cache[filename]
|
return _namespace_cache[filename]
|
||||||
|
|
||||||
|
|
||||||
|
_available_namespaces: list[tuple[str, str]] = []
|
||||||
|
|
||||||
|
|
||||||
|
def get_available_namespaces() -> T.List[T.Tuple[str, str]]:
|
||||||
|
if len(_available_namespaces):
|
||||||
|
return _available_namespaces
|
||||||
|
|
||||||
|
search_paths: list[str] = [
|
||||||
|
*GIRepository.Repository.get_search_path(),
|
||||||
|
*_user_search_paths,
|
||||||
|
]
|
||||||
|
|
||||||
|
for search_path in search_paths:
|
||||||
|
for filename in os.listdir(search_path):
|
||||||
|
if filename.endswith(".typelib"):
|
||||||
|
namespace, version = filename.removesuffix(".typelib").rsplit("-", 1)
|
||||||
|
_available_namespaces.append((namespace, version))
|
||||||
|
|
||||||
|
return _available_namespaces
|
||||||
|
|
||||||
|
|
||||||
def get_xml(namespace: str, version: str):
|
def get_xml(namespace: str, version: str):
|
||||||
search_paths = []
|
search_paths = []
|
||||||
|
|
||||||
|
@ -1011,9 +1032,11 @@ class GirContext:
|
||||||
ns = ns or "Gtk"
|
ns = ns or "Gtk"
|
||||||
|
|
||||||
if ns not in self.namespaces and ns not in self.not_found_namespaces:
|
if ns not in self.namespaces and ns not in self.not_found_namespaces:
|
||||||
|
all_available = list(set(ns for ns, _version in get_available_namespaces()))
|
||||||
|
|
||||||
raise CompileError(
|
raise CompileError(
|
||||||
f"Namespace {ns} was not imported",
|
f"Namespace {ns} was not imported",
|
||||||
did_you_mean=(ns, self.namespaces.keys()),
|
did_you_mean=(ns, all_available),
|
||||||
)
|
)
|
||||||
|
|
||||||
def validate_type(self, name: str, ns: str) -> None:
|
def validate_type(self, name: str, ns: str) -> None:
|
||||||
|
|
|
@ -55,7 +55,16 @@ class TypeName(AstNode):
|
||||||
@validate("namespace")
|
@validate("namespace")
|
||||||
def gir_ns_exists(self):
|
def gir_ns_exists(self):
|
||||||
if not self.tokens["extern"]:
|
if not self.tokens["extern"]:
|
||||||
self.root.gir.validate_ns(self.tokens["namespace"])
|
try:
|
||||||
|
self.root.gir.validate_ns(self.tokens["namespace"])
|
||||||
|
except CompileError as e:
|
||||||
|
ns = self.tokens["namespace"]
|
||||||
|
e.actions = [
|
||||||
|
self.root.import_code_action(n, version)
|
||||||
|
for n, version in gir.get_available_namespaces()
|
||||||
|
if n == ns
|
||||||
|
]
|
||||||
|
raise e
|
||||||
|
|
||||||
@validate()
|
@validate()
|
||||||
def deprecated(self) -> None:
|
def deprecated(self) -> None:
|
||||||
|
|
|
@ -99,6 +99,18 @@ class UI(AstNode):
|
||||||
and self.template.class_name.glib_type_name == id
|
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
|
||||||
|
|
||||||
|
return CodeAction(
|
||||||
|
f"Import {ns} {version}",
|
||||||
|
f"\nusing {ns} {version};",
|
||||||
|
Range(pos, pos, self.group.text),
|
||||||
|
)
|
||||||
|
|
||||||
@context(ScopeCtx)
|
@context(ScopeCtx)
|
||||||
def scope_ctx(self) -> ScopeCtx:
|
def scope_ctx(self) -> ScopeCtx:
|
||||||
return ScopeCtx(node=self)
|
return ScopeCtx(node=self)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue