More work to get LSP functioning. GOTO partially working

This commit is contained in:
itdominator 2023-11-05 23:22:41 -06:00
parent 27ab95c065
commit 839f4df5ef
3 changed files with 107 additions and 39 deletions

View File

@ -55,7 +55,13 @@ class LSPController:
if not language or not server_proc: return False if not language or not server_proc: return False
json_rpc_endpoint = pylspclient.JsonRpcEndpoint(server_proc.stdin, server_proc.stdout) json_rpc_endpoint = pylspclient.JsonRpcEndpoint(server_proc.stdin, server_proc.stdout)
lsp_endpoint = pylspclient.LspEndpoint(json_rpc_endpoint)
callbacks = {
"textDocument/symbolStatus": print,
"textDocument/publishDiagnostics": self.blame,
}
lsp_endpoint = pylspclient.LspEndpoint(json_rpc_endpoint, notify_callbacks = callbacks)
lsp_client = pylspclient.LspClient(lsp_endpoint) lsp_client = pylspclient.LspClient(lsp_endpoint)
self.lsp_clients[language] = lsp_client self.lsp_clients[language] = lsp_client
@ -70,11 +76,19 @@ class LSPController:
read_pipe.start() read_pipe.start()
return server_proc return server_proc
def blame(self, response):
for d in response['diagnostics']:
if d['severity'] == 1:
print(f"An error occurs in {response['uri']} at {d['range']}:")
print(f"\t[{d['source']}] {d['message']}")
def _shutting_down(self): def _shutting_down(self):
keys = self.lsp_clients.keys() keys = self.lsp_clients.keys()
for key in keys: for key in keys:
print(f"LSP Server: ( {key} ) Shutting Down...") print(f"LSP Server: ( {key} ) Shutting Down...")
self.lsp_clients[key].shutdown() self.lsp_clients[key].shutdown()
self.lsp_clients[key].exit() self.lsp_clients[key].exit()

View File

@ -12,6 +12,12 @@ from .lsp_controller import LSPController
class LSPPliginException(Exception):
...
class Plugin(PluginBase): class Plugin(PluginBase):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@ -90,6 +96,12 @@ class Plugin(PluginBase):
else: else:
self.lsp_client = self.load_lsp_server() 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)
def load_lsp_server(self): def load_lsp_server(self):
command = self.lsp_servers_config[self._file_type]["command"] command = self.lsp_servers_config[self._file_type]["command"]
if command: if command:
@ -98,13 +110,11 @@ class Plugin(PluginBase):
if client_created: if client_created:
return self.lsp_controller.lsp_clients[self._file_type] return self.lsp_controller.lsp_clients[self._file_type]
else:
text = f"LSP could not be created for file type: {self._file_type} ..."
self._event_system.emit("bubble_message", ("warning", self.name, text,))
text = f"LSP could not be created for file type: {self._file_type} ..."
self._event_system.emit("bubble_message", ("warning", self.name, text,))
return None return None
def _buffer_changed_first_load(self, buffer): def _buffer_changed_first_load(self, buffer):
if self.lsp_disabled: return if self.lsp_disabled: return
@ -112,18 +122,73 @@ class Plugin(PluginBase):
def _buffer_changed(self, buffer): def _buffer_changed(self, buffer):
if self.lsp_disabled: return if self.lsp_disabled: return
self._do_completion()
def _do_completion(self, is_invoked = False):
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
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)
def _do_goto(self): def _do_goto(self):
if self.lsp_disabled: return if self.lsp_disabled: return
iter = self._buffer.get_iter_at_mark( self._buffer.get_insert() ) iter = self._buffer.get_iter_at_mark( self._buffer.get_insert() )
line = iter.get_line() + 1 line = iter.get_line()
offset = iter.get_line_offset() + 1 offset = iter.get_line_offset()
uri = self._active_src_view.get_current_filepath().get_uri() uri = self._active_src_view.get_current_filepath().get_uri()
result = self.lsp_client.declaration(pylspclient.lsp_structs.TextDocumentIdentifier(uri), pylspclient.lsp_structs.Position(line, offset)) results = self.lsp_client.definition(
pylspclient.lsp_structs.TextDocumentIdentifier(uri),
print(result) 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)
def _do_get_implementation(self): def _do_get_implementation(self):
if self.lsp_disabled: return 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)
)

View File

@ -95,8 +95,12 @@ class LspClient(object):
:param TextDocumentItem textDocument: The document that was opened. :param TextDocumentItem textDocument: The document that was opened.
""" """
self.lsp_endpoint.send_notification("textDocument/didClose", textDocument = textDocument)
return self.lsp_endpoint.send_notification("textDocument/didOpen", textDocument = textDocument) return self.lsp_endpoint.send_notification("textDocument/didOpen", textDocument = textDocument)
def didClose(self, textDocument):
return self.lsp_endpoint.send_notification("textDocument/didClose", textDocument = textDocument)
def didChange(self, textDocument, contentChanges): def didChange(self, textDocument, contentChanges):
""" """
The document change notification is sent from the client to the server to signal changes to a text document. The document change notification is sent from the client to the server to signal changes to a text document.
@ -121,6 +125,7 @@ class LspClient(object):
""" """
result_dict = self.lsp_endpoint.call_method( "textDocument/documentSymbol", textDocument=textDocument ) result_dict = self.lsp_endpoint.call_method( "textDocument/documentSymbol", textDocument=textDocument )
if not result_dict: return []
return [lsp_structs.SymbolInformation(**sym) for sym in result_dict] return [lsp_structs.SymbolInformation(**sym) for sym in result_dict]
def declaration(self, textDocument, position): def declaration(self, textDocument, position):
@ -142,6 +147,8 @@ class LspClient(object):
position = position position = position
) )
if not result_dict: return []
if "uri" in result_dict: if "uri" in result_dict:
return lsp_structs.Location(**result_dict) return lsp_structs.Location(**result_dict)
@ -162,6 +169,7 @@ class LspClient(object):
position = position position = position
) )
if not result_dict: return []
return [lsp_structs.Location(**loc) for loc in result_dict] return [lsp_structs.Location(**loc) for loc in result_dict]
def typeDefinition(self, textDocument, position): def typeDefinition(self, textDocument, position):
@ -179,6 +187,7 @@ class LspClient(object):
position = position position = position
) )
if not result_dict: return []
return [lsp_structs.Location(**loc) for loc in result_dict] return [lsp_structs.Location(**loc) for loc in result_dict]
def signatureHelp(self, textDocument, position): def signatureHelp(self, textDocument, position):
@ -195,6 +204,7 @@ class LspClient(object):
position = position position = position
) )
if not result_dict: return []
return lsp_structs.SignatureHelp(**result_dict) return lsp_structs.SignatureHelp(**result_dict)
def completion(self, textDocument, position, context): def completion(self, textDocument, position, context):
@ -214,35 +224,13 @@ class LspClient(object):
position = position, position = position,
context = context context = context
) )
if not result_dict: return []
if "isIncomplete" in result_dict: if "isIncomplete" in result_dict:
return lsp_structs.CompletionList(**result_dict) return lsp_structs.CompletionList(**result_dict)
return [lsp_structs.CompletionItem(**loc) for loc in result_dict] return [lsp_structs.CompletionItem(**loc) for loc in result_dict]
def definition(self, textDocument, position):
"""
The go to definition request is sent from the client to the server to
resolve the declaration location of a symbol at a given text document
position.
The result type LocationLink[] got introduce with version 3.14.0 and
depends in the corresponding client capability
`clientCapabilities.textDocument.declaration.linkSupport`.
:param TextDocumentItem textDocument: The text document.
:param Position position: The position inside the text document.
"""
result_dict = self.lsp_endpoint.call_method("textDocument/definition",
textDocument = textDocument,
position = position)
if "uri" in result_dict:
return lsp_structs.Location(**result_dict)
return [lsp_structs.Location(**l)
if "uri" in l else lsp_structs.LinkLocation(**l) for l in result_dict]
def references(self, textDocument, position): def references(self, textDocument, position):
""" """
The references request is sent from the client to the server to resolve The references request is sent from the client to the server to resolve
@ -257,4 +245,5 @@ class LspClient(object):
textDocument = textDocument, textDocument = textDocument,
position = position) position = position)
if not result_dict: return []
return [lsp_structs.Location(**loc) for loc in result_dict] return [lsp_structs.Location(**loc) for loc in result_dict]