import logging from . import lsp from .workspace import Workspace log = logging.getLogger(__name__) class VhdlLanguageServer(object): def __init__(self): self.workspace = None self.lsp = None self._shutdown = False self.dispatcher = { "initialize": self.initialize, "initialized": self.initialized, "shutdown": self.shutdown, "$/setTraceNotification": self.setTraceNotification, "$/setTrace": self.setTrace, "$/cancelRequest": self.cancelRequest, "textDocument/didOpen": self.textDocument_didOpen, "textDocument/didChange": self.textDocument_didChange, "textDocument/didClose": self.textDocument_didClose, "textDocument/didSave": self.textDocument_didSave, "textDocument/hover": self.textDocument_hover, "textDocument/definition": self.textDocument_definition, "textDocument/implementation": self.textDocument_implementation, "textDocument/documentSymbol": self.textDocument_documentSymbol, "textDocument/codeAction": self.textDocument_codeAction, # 'textDocument/completion': self.completion, "textDocument/rangeFormatting": self.textDocument_rangeFormatting, "workspace/xShowAllFiles": self.workspace_xShowAllFiles, "workspace/xGetAllEntities": self.workspace_xGetAllEntities, "workspace/xGetEntityInterface": self.workspace_xGetEntityInterface, } def set_lsp(self, server): self.lsp = server def shutdown(self): self.lsp.shutdown() def setTraceNotification(self, value): pass def setTrace(self, value): pass def cancelRequest(self, id): pass def capabilities(self): server_capabilities = { "textDocumentSync": { "openClose": True, "change": lsp.TextDocumentSyncKind.INCREMENTAL, "save": {"includeText": True}, }, "hoverProvider": True, # 'completionProvider': False, # 'signatureHelpProvider': { # 'triggerCharacters': ['(', ','] # }, "definitionProvider": True, "implementationProvider": True, "referencesProvider": False, "documentHighlightProvider": False, "documentSymbolProvider": True, "codeActionProvider": False, "documentFormattingProvider": False, "documentRangeFormattingProvider": True, "renameProvider": False, } return server_capabilities def initialize(self, processId, rootPath, capabilities, rootUri=None, initializationOptions=None, **_): log.debug( "Language server initialize: pid=%s uri=%s path=%s options=%s", processId, rootUri, rootPath, initializationOptions, ) if rootUri is None: rootUri = lsp.path_to_uri(rootPath) if rootPath is not None else "" self.workspace = Workspace(rootUri, self.lsp) # Get our capabilities return {"capabilities": self.capabilities()} def initialized(self): # Event when the client is fully initialized. return None def textDocument_didOpen(self, textDocument=None): doc_uri = textDocument["uri"] self.workspace.put_document(doc_uri, textDocument["text"], version=textDocument.get("version")) self.lint(doc_uri) def textDocument_didChange(self, textDocument=None, contentChanges=None, **_kwargs): doc_uri = textDocument["uri"] new_version = textDocument.get("version") self.workspace.apply_changes(doc_uri, contentChanges, new_version) def lint(self, doc_uri): self.workspace.lint(doc_uri) def textDocument_didClose(self, textDocument=None, **_kwargs): self.workspace.rm_document(textDocument["uri"]) def textDocument_didSave(self, textDocument=None, text=None, **_kwargs): if text is not None: # Sanity check: check we have the same content for the document. self.workspace.check_document(textDocument["uri"], text) else: log.debug("did save - no text") self.lint(textDocument["uri"]) def textDocument_definition(self, textDocument=None, position=None): return self.workspace.goto_definition(textDocument["uri"], position) def textDocument_implementation(self, textDocument=None, position=None): return self.workspace.goto_implementation(textDocument["uri"], position) def textDocument_documentSymbol(self, textDocument=None): doc = self.workspace.get_or_create_document(textDocument["uri"]) return doc.document_symbols() def textDocument_rangeFormatting(self, textDocument=None, range=None, options=None): doc_uri = textDocument["uri"] doc = self.workspace.get_document(doc_uri) assert doc is not None, "Try to format a non-loaded document" res = doc.format_range(range) if res is not None: self.lint(doc_uri) return res def textDocument_hover(self, textDocument=None, position=None): return self.workspace.hover(textDocument["uri"], position) def textDocument_codeAction(self, textDocument=None, range=None, context=None): # Not yet implemented. # * reorder associations (but keep comments !) # * add missing associations (all or only IN) # * add formal in assocs return None def m_workspace__did_change_configuration(self, _settings=None): for doc_uri in self.workspace.documents: self.lint(doc_uri) def m_workspace__did_change_watched_files(self, **_kwargs): # Externally changed files may result in changed diagnostics for doc_uri in self.workspace.documents: self.lint(doc_uri) def workspace_xShowAllFiles(self): return self.workspace.x_show_all_files() def workspace_xGetAllEntities(self): return self.workspace.x_get_all_entities() def workspace_xGetEntityInterface(self, library, name): return self.workspace.x_get_entity_interface(library, name)