diff options
Diffstat (limited to 'python/vhdl_langserver/document.py')
-rw-r--r-- | python/vhdl_langserver/document.py | 226 |
1 files changed, 0 insertions, 226 deletions
diff --git a/python/vhdl_langserver/document.py b/python/vhdl_langserver/document.py deleted file mode 100644 index 82d11fe56..000000000 --- a/python/vhdl_langserver/document.py +++ /dev/null @@ -1,226 +0,0 @@ -import ctypes -import logging -import os -import libghdl.thin.name_table as name_table -import libghdl.thin.files_map as files_map -import libghdl.thin.files_map_editor as files_map_editor -import libghdl.thin.libraries as libraries -import libghdl.thin.vhdl.nodes as nodes -import libghdl.thin.vhdl.sem_lib as sem_lib -import libghdl.thin.vhdl.sem as sem -import libghdl.thin.vhdl.formatters as formatters - -from . import symbols, references - -log = logging.getLogger(__name__) - - -class Document(object): - # The encoding used for the files. - # Unfortunately this is not fully reliable. The client can read the - # file using its own view of the encoding. It then pass the document - # to the server using unicode(utf-8). Then the document is converted - # back to bytes using this encoding. And we hope the result would be - # the same as the file. Because VHDL uses the iso 8859-1 character - # set, we use the same encoding. The client should also use 8859-1. - encoding = "iso-8859-1" - - initial_gap_size = 4096 - - def __init__(self, uri, sfe=None, version=None): - self.uri = uri - self.version = version - self._fe = sfe - self.gap_size = Document.initial_gap_size - self._tree = nodes.Null_Iir - - @staticmethod - def load(source, dirname, filename): - # Write text to file buffer. - src_bytes = source.encode(Document.encoding, "replace") - src_len = len(src_bytes) - buf_len = src_len + Document.initial_gap_size - fileid = name_table.Get_Identifier(filename.encode("utf-8")) - if os.path.isabs(filename): - dirid = name_table.Null_Identifier - else: - dirid = name_table.Get_Identifier(dirname.encode("utf-8")) - sfe = files_map.Reserve_Source_File(dirid, fileid, buf_len) - files_map_editor.Fill_Text(sfe, ctypes.c_char_p(src_bytes), src_len) - return sfe - - def reload(self, source): - """Reload the source of a document. """ - src_bytes = source.encode(Document.encoding, "replace") - files_map_editor.Fill_Text(self._fe, ctypes.c_char_p(src_bytes), len(src_bytes)) - - def __str__(self): - return str(self.uri) - - def apply_change(self, change): - """Apply a change to the document.""" - text = change["text"] - change_range = change.get("range") - - text_bytes = text.encode(Document.encoding, "replace") - - if not change_range: - # The whole file has changed - raise AssertionError - # if len(text_bytes) < thin.Files_Map.Get_Buffer_Length(self._fe): - # xxxx_replace - # else: - # xxxx_free - # xxxx_allocate - # return - - start_line = change_range["start"]["line"] - start_col = change_range["start"]["character"] - end_line = change_range["end"]["line"] - end_col = change_range["end"]["character"] - - status = files_map_editor.Replace_Text( - self._fe, - start_line + 1, - start_col, - end_line + 1, - end_col, - ctypes.c_char_p(text_bytes), - len(text_bytes), - ) - if status: - return - - # Failed to replace text. - # Increase size - self.gap_size *= 2 - fileid = files_map.Get_File_Name(self._fe) - dirid = files_map.Get_Directory_Name(self._fe) - buf_len = files_map.Get_File_Length(self._fe) + len(text_bytes) + self.gap_size - files_map.Discard_Source_File(self._fe) - new_sfe = files_map.Reserve_Source_File(dirid, fileid, buf_len) - files_map_editor.Copy_Source_File(new_sfe, self._fe) - files_map.Free_Source_File(self._fe) - self._fe = new_sfe - status = files_map_editor.Replace_Text( - self._fe, - start_line + 1, - start_col, - end_line + 1, - end_col, - ctypes.c_char_p(text_bytes), - len(text_bytes), - ) - assert status - - def check_document(self, text): - log.debug("Checking document: %s", self.uri) - - text_bytes = text.encode(Document.encoding, "replace") - - files_map_editor.Check_Buffer_Content( - self._fe, ctypes.c_char_p(text_bytes), len(text_bytes) - ) - - @staticmethod - def add_to_library(tree): - # Detach the chain of units. - unit = nodes.Get_First_Design_Unit(tree) - nodes.Set_First_Design_Unit(tree, nodes.Null_Iir) - # FIXME: free the design file ? - tree = nodes.Null_Iir - # Analyze unit after unit. - while unit != nodes.Null_Iir: - # Pop the first unit. - next_unit = nodes.Get_Chain(unit) - nodes.Set_Chain(unit, nodes.Null_Iir) - lib_unit = nodes.Get_Library_Unit(unit) - if ( - lib_unit != nodes.Null_Iir - and nodes.Get_Identifier(unit) != name_table.Null_Identifier - ): - # Put the unit (only if it has a library unit) in the library. - libraries.Add_Design_Unit_Into_Library(unit, False) - tree = nodes.Get_Design_File(unit) - unit = next_unit - return tree - - def parse_document(self): - """Parse a document and put the units in the library""" - assert self._tree == nodes.Null_Iir - tree = sem_lib.Load_File(self._fe) - if tree == nodes.Null_Iir: - return - self._tree = Document.add_to_library(tree) - log.debug("add_to_library(%u) -> %u", tree, self._tree) - if self._tree == nodes.Null_Iir: - return - nodes.Set_Design_File_Source(self._tree, self._fe) - - def compute_diags(self): - log.debug("parse doc %d %s", self._fe, self.uri) - self.parse_document() - if self._tree == nodes.Null_Iir: - # No units, nothing to add. - return - # Semantic analysis. - unit = nodes.Get_First_Design_Unit(self._tree) - while unit != nodes.Null_Iir: - sem.Semantic(unit) - nodes.Set_Date_State(unit, nodes.Date_State.Analyze) - unit = nodes.Get_Chain(unit) - - def flatten_symbols(self, syms, parent): - res = [] - for s in syms: - s["location"] = {"uri": self.uri, "range": s["range"]} - del s["range"] - s.pop("detail", None) - if parent is not None: - s["containerName"] = parent - res.append(s) - children = s.pop("children", None) - if children is not None: - res.extend(self.flatten_symbols(children, s)) - return res - - def document_symbols(self): - log.debug("document_symbols") - if self._tree == nodes.Null_Iir: - return [] - syms = symbols.get_symbols_chain( - self._fe, nodes.Get_First_Design_Unit(self._tree) - ) - return self.flatten_symbols(syms, None) - - def position_to_location(self, position): - pos = files_map.File_Line_To_Position(self._fe, position["line"] + 1) - return files_map.File_Pos_To_Location(self._fe, pos) + position["character"] - - def goto_definition(self, position): - loc = self.position_to_location(position) - return references.goto_definition(self._tree, loc) - - def format_range(self, rng): - first_line = rng["start"]["line"] + 1 - last_line = rng["end"]["line"] + (1 if rng["end"]["character"] != 0 else 0) - if last_line < first_line: - return None - if self._tree == nodes.Null_Iir: - return None - hand = formatters.Allocate_Handle() - formatters.Indent_String(self._tree, hand, first_line, last_line) - buffer = formatters.Get_C_String(hand) - buf_len = formatters.Get_Length(hand) - newtext = buffer[:buf_len].decode(Document.encoding) - res = [ - { - "range": { - "start": {"line": first_line - 1, "character": 0}, - "end": {"line": last_line, "character": 0}, - }, - "newText": newtext, - } - ] - formatters.Free_Handle(hand) - return res |