aboutsummaryrefslogtreecommitdiffstats
path: root/pyGHDL/lsp/vhdl_ls.py
diff options
context:
space:
mode:
authorumarcor <unai.martinezcorral@ehu.eus>2020-12-27 22:10:38 +0100
committerumarcor <unai.martinezcorral@ehu.eus>2020-12-27 23:13:21 +0100
commitbf74a0983c2d534e217e7312ab559ca8929ff8a2 (patch)
treefb630d5b83afc2f112996ebb5f1eac44de868132 /pyGHDL/lsp/vhdl_ls.py
parent340fc792bba2ffdb4f930bc427a39ea3a1b659b2 (diff)
downloadghdl-bf74a0983c2d534e217e7312ab559ca8929ff8a2.tar.gz
ghdl-bf74a0983c2d534e217e7312ab559ca8929ff8a2.tar.bz2
ghdl-bf74a0983c2d534e217e7312ab559ca8929ff8a2.zip
rework 'python', rename to 'pyGHDL'
* Rename 'python' to 'pyGHDL'. * Let 'thin' be 'libghdl'. * Move move 'pyutils.py' from 'python/libghdl/vhdl' to a separate package ('pyGHDL/libghdl/utils/'). * Update 'vhdl_langserver' accordingly. * Rename 'vhdl_langserver' to 'lsp'. * Move 'ghdl-ls' to 'pyGHDL/cli'.
Diffstat (limited to 'pyGHDL/lsp/vhdl_ls.py')
-rw-r--r--pyGHDL/lsp/vhdl_ls.py150
1 files changed, 150 insertions, 0 deletions
diff --git a/pyGHDL/lsp/vhdl_ls.py b/pyGHDL/lsp/vhdl_ls.py
new file mode 100644
index 000000000..61c4aed23
--- /dev/null
+++ b/pyGHDL/lsp/vhdl_ls.py
@@ -0,0 +1,150 @@
+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,
+ "textDocument/didOpen": self.textDocument_didOpen,
+ "textDocument/didChange": self.textDocument_didChange,
+ "textDocument/didClose": self.textDocument_didClose,
+ "textDocument/didSave": self.textDocument_didSave,
+ # 'textDocument/hover': self.hover,
+ "textDocument/definition": self.textDocument_definition,
+ "textDocument/documentSymbol": self.textDocument_documentSymbol,
+ # '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 capabilities(self):
+ server_capabilities = {
+ "textDocumentSync": {
+ "openClose": True,
+ "change": lsp.TextDocumentSyncKind.INCREMENTAL,
+ "save": {"includeText": True},
+ },
+ "hoverProvider": False,
+ # 'completionProvider': False,
+ # 'signatureHelpProvider': {
+ # 'triggerCharacters': ['(', ',']
+ # },
+ "definitionProvider": 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 initialized with %s %s %s %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_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 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)