Newton_Editor/plugins/lsp_client/plugin.py

194 lines
7.7 KiB
Python
Raw Normal View History

2023-11-04 19:38:20 +00:00
# Python imports
2023-11-05 05:36:55 +00:00
import os
import json
2023-11-04 19:38:20 +00:00
# Lib imports
# Application imports
from plugins.plugin_base import PluginBase
from .lsp_controller import LSPController
class LSPPliginException(Exception):
...
2023-11-04 19:38:20 +00:00
class Plugin(PluginBase):
def __init__(self):
super().__init__()
2023-11-05 05:36:55 +00:00
self.name = "LSP Client" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus
# where self.name should not be needed for message comms
self.lsp_config_path: str = os.path.dirname(os.path.realpath(__file__)) + "/../../lsp_servers_config.json"
self.lsp_servers_config: dict = {}
self.lsp_controller = None
self.lsp_client = None
self.lsp_disabled = False
2023-11-04 19:38:20 +00:00
def generate_reference_ui_element(self):
...
def run(self):
2023-11-05 05:36:55 +00:00
if os.path.exists(self.lsp_config_path):
with open(self.lsp_config_path, "r") as f:
self.lsp_servers_config = json.load(f)
else:
self.lsp_disabled = True
text = f"LSP NOT Enabled.\nFile:\n\t{self.lsp_config_path}\ndoes no exsist..."
2023-11-04 19:38:20 +00:00
self._event_system.emit("bubble_message", ("warning", self.name, text,))
2023-11-05 05:36:55 +00:00
if not self.lsp_disabled:
self.lsp_controller = LSPController()
2023-11-04 19:38:20 +00:00
# language_id = pylspclient.lsp_structs.LANGUAGE_IDENTIFIER.C
# version = 1
# self.lsp_client.didOpen(pylspclient.lsp_structs.TextDocumentItem(uri, language_id, version, text))
# try:
# symbols = self.lsp_client.documentSymbol(pylspclient.lsp_structs.TextDocumentIdentifier(uri))
# for symbol in symbols:
# print(symbol.name)
# except pylspclient.lsp_structs.ResponseError:
# documentSymbol is supported from version 8.
# print("Failed to document symbols")
# ...
# self.lsp_client.definition(pylspclient.lsp_structs.TextDocumentIdentifier(uri), pylspclient.lsp_structs.Position(14, 4))
# self.lsp_client.signatureHelp(pylspclient.lsp_structs.TextDocumentIdentifier(uri), pylspclient.lsp_structs.Position(14, 4))
# self.lsp_client.definition(pylspclient.lsp_structs.TextDocumentIdentifier(uri), pylspclient.lsp_structs.Position(14, 4))
# self.lsp_client.completion(pylspclient.lsp_structs.TextDocumentIdentifier(uri), pylspclient.lsp_structs.Position(14, 4), pylspclient.lsp_structs.CompletionContext(pylspclient.lsp_structs.CompletionTriggerKind.Invoked))
def subscribe_to_events(self):
self._event_system.subscribe("shutting_down", self._shutting_down)
self._event_system.subscribe("set_active_src_view", self._set_active_src_view)
self._event_system.subscribe("buffer_changed_first_load", self._buffer_changed_first_load)
self._event_system.subscribe("buffer_changed", self._buffer_changed)
self._event_system.subscribe("do_goto", self._do_goto)
self._event_system.subscribe("do_get_implementation", self._do_get_implementation)
def _shutting_down(self):
2023-11-05 05:36:55 +00:00
if self.lsp_controller:
self.lsp_controller._shutting_down()
2023-11-04 19:38:20 +00:00
def _set_active_src_view(self, source_view):
2023-11-05 05:36:55 +00:00
if self.lsp_disabled: return
2023-11-04 19:38:20 +00:00
self._active_src_view = source_view
self._buffer = source_view.get_buffer()
self._file_type = source_view.get_filetype()
2023-11-05 05:36:55 +00:00
if self._file_type in self.lsp_servers_config.keys():
self.set_lsp_server()
else:
text = f"LSP could not be created for file type: {self._file_type} ..."
self._event_system.emit("bubble_message", ("warning", self.name, text,))
def set_lsp_server(self):
if self._file_type in self.lsp_controller.lsp_clients.keys():
self.lsp_client = self.lsp_controller.lsp_clients[self._file_type]
else:
self.lsp_client = self.load_lsp_server()
if self.lsp_client:
# Note: textDocument/didClose is actually called from the open api beforehand
# to insure no more than one instanmce of a file is opened
uri = self._active_src_view.get_current_filepath().get_uri()
self.register_opened_file(self._file_type, uri)
2023-11-05 05:36:55 +00:00
def load_lsp_server(self):
command = self.lsp_servers_config[self._file_type]["command"]
if command:
server_proc = self.lsp_controller.create_lsp_server(command)
client_created = self.lsp_controller.create_client(self._file_type, server_proc)
if client_created:
return self.lsp_controller.lsp_clients[self._file_type]
text = f"LSP could not be created for file type: {self._file_type} ..."
self._event_system.emit("bubble_message", ("warning", self.name, text,))
2023-11-05 05:36:55 +00:00
return None
2023-11-04 19:38:20 +00:00
def _buffer_changed_first_load(self, buffer):
2023-11-05 05:36:55 +00:00
if self.lsp_disabled: return
2023-11-04 19:38:20 +00:00
self._buffer = buffer
def _buffer_changed(self, buffer):
2023-11-05 05:36:55 +00:00
if self.lsp_disabled: return
self._do_completion()
2023-11-04 19:38:20 +00:00
def _do_completion(self, is_invoked = False):
2023-11-05 05:36:55 +00:00
if self.lsp_disabled: return
uri = self._active_src_view.get_current_filepath().get_uri()
iter = self._buffer.get_iter_at_mark( self._buffer.get_insert() )
line = iter.get_line()
offset = iter.get_line_offset()
trigger = pylspclient.lsp_structs.CompletionTriggerKind.TriggerCharacter
_char = iter.get_char()
trigger = None
if _char in [".", " "]:
trigger = pylspclient.lsp_structs.CompletionTriggerKind.TriggerCharacter
elif is_invoked:
trigger = pylspclient.lsp_structs.CompletionTriggerKind.Invoked
else:
trigger = pylspclient.lsp_structs.CompletionTriggerKind.TriggerForIncompleteCompletions
2023-11-05 05:36:55 +00:00
result = self.lsp_client.completion(
pylspclient.lsp_structs.TextDocumentIdentifier(uri),
pylspclient.lsp_structs.Position(line, offset),
pylspclient.lsp_structs.CompletionContext(trigger, _char)
)
if result.items:
for item in result.items:
print(item.label)
else:
print(result.label)
2023-11-05 05:36:55 +00:00
def _do_goto(self):
if self.lsp_disabled: return
iter = self._buffer.get_iter_at_mark( self._buffer.get_insert() )
line = iter.get_line()
offset = iter.get_line_offset()
uri = self._active_src_view.get_current_filepath().get_uri()
results = self.lsp_client.definition(
pylspclient.lsp_structs.TextDocumentIdentifier(uri),
pylspclient.lsp_structs.Position(line, offset)
)
results = []
if len(results) == 1:
result = results[0]
file = result.uri[7:]
line = result.range.end.line
message = f"FILE|{file}:{line}"
self._event_system.emit("post_file_to_ipc", message)
2023-11-05 05:36:55 +00:00
2023-11-04 19:38:20 +00:00
def _do_get_implementation(self):
if self.lsp_disabled: return
results = self.lsp_client.declaration(pylspclient.lsp_structs.TextDocumentIdentifier(uri), pylspclient.lsp_structs.Position(line, offset))
def register_opened_file(self, language_id = "", uri = ""):
if not language_id or not uri: return
text = open(uri[7:], "r").read()
version = 1
self.lsp_client.didClose(
pylspclient.lsp_structs.TextDocumentItem(uri, language_id, version, text)
)
self.lsp_client.didOpen(
pylspclient.lsp_structs.TextDocumentItem(uri, language_id, version, text)
)