aboutsummaryrefslogtreecommitdiffstats
path: root/python/vhdl_langserver/document.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/vhdl_langserver/document.py')
-rw-r--r--python/vhdl_langserver/document.py226
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