aboutsummaryrefslogtreecommitdiffstats
path: root/pyGHDL
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2023-01-26 18:27:30 +0100
committerTristan Gingold <tgingold@free.fr>2023-01-26 21:56:33 +0100
commit446f15d3b4b410fc7a9443a6bd010e8d1db735bd (patch)
tree2865d0161e04e97bac8f1e3dc89dcf9391330618 /pyGHDL
parentab3c672925cb214be9d732835e891557a511b173 (diff)
downloadghdl-446f15d3b4b410fc7a9443a6bd010e8d1db735bd.tar.gz
ghdl-446f15d3b4b410fc7a9443a6bd010e8d1db735bd.tar.bz2
ghdl-446f15d3b4b410fc7a9443a6bd010e8d1db735bd.zip
pyGHDL/lsp: update, handle hover
Diffstat (limited to 'pyGHDL')
-rw-r--r--pyGHDL/lsp/document.py39
-rw-r--r--pyGHDL/lsp/lsp.py2
-rw-r--r--pyGHDL/lsp/references.py76
-rw-r--r--pyGHDL/lsp/vhdl_ls.py7
-rw-r--r--pyGHDL/lsp/workspace.py6
5 files changed, 111 insertions, 19 deletions
diff --git a/pyGHDL/lsp/document.py b/pyGHDL/lsp/document.py
index 2656606c6..1a6a20f39 100644
--- a/pyGHDL/lsp/document.py
+++ b/pyGHDL/lsp/document.py
@@ -9,6 +9,8 @@ import pyGHDL.libghdl.vhdl.nodes as nodes
import pyGHDL.libghdl.vhdl.sem_lib as sem_lib
import pyGHDL.libghdl.vhdl.sem as sem
import pyGHDL.libghdl.vhdl.formatters as formatters
+import pyGHDL.libghdl.vhdl.prints as prints
+import pyGHDL.libghdl.file_comments as file_comments
from . import symbols, references
@@ -197,7 +199,34 @@ class Document(object):
def goto_definition(self, position):
loc = self.position_to_location(position)
- return references.goto_definition(self._tree, loc)
+ return references.find_definition_by_loc(self._tree, loc)
+
+ def hover(self, position):
+ loc = self.position_to_location(position)
+ t = references.find_definition_by_loc(self._tree, loc)
+ if t is None:
+ return None
+
+ # Regenerate the declaration
+ hand = prints.Allocate_Handle()
+ prints.Print_String(t, hand)
+ buffer = prints.Get_C_String(hand)
+ buf_len = prints.Get_Length(hand)
+ if buf_len == 0:
+ res = None
+ else:
+ txt = ''
+ t_loc = nodes.Get_Location(t)
+ t_fe = files_map.Location_To_File(t_loc)
+ comm = file_comments.Find_First_Comment(t_fe, t)
+ while comm != file_comments.No_Comment_Index:
+ txt += file_comments.Get_Comment(t_fe, comm) + '\n'
+ comm = file_comments.Get_Next_Comment(t_fe, comm)
+ newtext = buffer[:buf_len].decode(Document.encoding)
+ txt += "```vhdl\n" + newtext + "\n```"
+ res = {'contents': { 'kind': 'markdown', 'value': txt }}
+ prints.Free_Handle(hand)
+ return res
def format_range(self, rng):
first_line = rng["start"]["line"] + 1
@@ -206,10 +235,10 @@ class Document(object):
return None
if self._tree == nodes.Null_Iir:
return None
- hand = formatters.Allocate_Handle()
+ hand = prints.Allocate_Handle()
formatters.Indent_String(self._tree, hand, first_line, last_line)
- buffer = formatters.Get_C_String(hand)
- buf_len = formatters.Get_Length(hand)
+ buffer = prints.Get_C_String(hand)
+ buf_len = prints.Get_Length(hand)
newtext = buffer[:buf_len].decode(Document.encoding)
res = [
{
@@ -220,5 +249,5 @@ class Document(object):
"newText": newtext,
}
]
- formatters.Free_Handle(hand)
+ prints.Free_Handle(hand)
return res
diff --git a/pyGHDL/lsp/lsp.py b/pyGHDL/lsp/lsp.py
index 0b392ea84..32a64b3ea 100644
--- a/pyGHDL/lsp/lsp.py
+++ b/pyGHDL/lsp/lsp.py
@@ -126,7 +126,7 @@ class LanguageProtocolServer(object):
log.error("Unexpected reply for %s", tid)
return
params = msg.get("params", None)
- # Fix capitalization issues on windws.
+ # Fix capitalization issues on windows.
if is_windows:
normalize_rpc_file_uris(msg)
fmethod = self.handler.dispatcher.get(method, None)
diff --git a/pyGHDL/lsp/references.py b/pyGHDL/lsp/references.py
index e99f473c2..2adde0fed 100644
--- a/pyGHDL/lsp/references.py
+++ b/pyGHDL/lsp/references.py
@@ -22,14 +22,14 @@ def find_def(n, loc):
if n == nodes.Null_Iir:
return None
k = nodes.Get_Kind(n)
- if k in [
+ if k in (
nodes.Iir_Kind.Simple_Name,
nodes.Iir_Kind.Character_Literal,
nodes.Iir_Kind.Operator_Symbol,
nodes.Iir_Kind.Selected_Name,
nodes.Iir_Kind.Attribute_Name,
nodes.Iir_Kind.Selected_Element,
- ]:
+ ):
n_loc = nodes.Get_Location(n)
if loc >= n_loc:
ident = nodes.Get_Identifier(n)
@@ -48,6 +48,57 @@ def find_def(n, loc):
return res
unit = nodes.Get_Library_Unit(n)
return find_def(unit, loc)
+ elif k in (
+ nodes.Iir_Kind.Identity_Operator,
+ nodes.Iir_Kind.Negation_Operator,
+ nodes.Iir_Kind.Addition_Operator,
+ nodes.Iir_Kind.Substraction_Operator,
+ nodes.Iir_Kind.Multiplication_Operator,
+ nodes.Iir_Kind.Division_Operator,
+ nodes.Iir_Kind.Concatenation_Operator,
+ nodes.Iir_Kind.Equality_Operator,
+ nodes.Iir_Kind.Less_Than_Operator,
+ nodes.Iir_Kind.Greater_Than_Operator,
+ ):
+ n_loc = nodes.Get_Location(n)
+ if loc == n_loc:
+ return n
+ elif k in (
+ nodes.Iir_Kind.Or_Operator,
+ nodes.Iir_Kind.Inequality_Operator,
+ nodes.Iir_Kind.Less_Than_Or_Equal_Operator,
+ nodes.Iir_Kind.Greater_Than_Or_Equal_Operator,
+ nodes.Iir_Kind.Condition_Operator,
+ nodes.Iir_Kind.Exponentiation_Operator,
+ ):
+ n_loc = nodes.Get_Location(n)
+ if n_loc <= loc <= n_loc + 1:
+ return n
+ elif k in (
+ nodes.Iir_Kind.Absolute_Operator,
+ nodes.Iir_Kind.Not_Operator,
+ nodes.Iir_Kind.And_Operator,
+ nodes.Iir_Kind.Nor_Operator,
+ nodes.Iir_Kind.Xor_Operator,
+ nodes.Iir_Kind.Sll_Operator,
+ nodes.Iir_Kind.Sla_Operator,
+ nodes.Iir_Kind.Srl_Operator,
+ nodes.Iir_Kind.Sra_Operator,
+ nodes.Iir_Kind.Rol_Operator,
+ nodes.Iir_Kind.Ror_Operator,
+ nodes.Iir_Kind.Modulus_Operator,
+ nodes.Iir_Kind.Remainder_Operator,
+ ):
+ n_loc = nodes.Get_Location(n)
+ if n_loc <= loc <= n_loc + 2:
+ return n
+ elif k in (
+ nodes.Iir_Kind.Nand_Operator,
+ nodes.Iir_Kind.Xnor_Operator,
+ ):
+ n_loc = nodes.Get_Location(n)
+ if n_loc <= loc <= n_loc + 3:
+ return n
# This is *much* faster than using node_iter!
for f in pyutils.fields_iter(n):
@@ -84,17 +135,20 @@ def find_def(n, loc):
return None
-
-def goto_definition(n, loc):
- """Return the declaration (as a node) under :param loc: or None."""
+def find_node_by_loc(n, loc):
+ """Return the denoting node for :param loc: or None."""
ref = find_def(n, loc)
log.debug("for loc %u found node %s", loc, ref)
+ return ref
+
+def find_definition_by_loc(n, loc):
+ """Return the declaration (as a node) under :param loc: or None."""
+ ref = find_node_by_loc(n, loc)
if ref is None:
return None
- log.debug(
- "for loc %u id=%s",
- loc,
- name_table.Get_Name_Ptr(nodes.Get_Identifier(ref)),
- )
- ent = nodes.Get_Named_Entity(ref)
+ k = nodes.Get_Kind(ref)
+ if k in nodes.Iir_Kinds.Denoting_Name or k == nodes.Iir_Kind.Selected_Element:
+ ent = nodes.Get_Named_Entity(ref)
+ else:
+ ent = nodes.Get_Implementation(ref)
return None if ent == nodes.Null_Iir else ent
diff --git a/pyGHDL/lsp/vhdl_ls.py b/pyGHDL/lsp/vhdl_ls.py
index dea9542b9..01474f746 100644
--- a/pyGHDL/lsp/vhdl_ls.py
+++ b/pyGHDL/lsp/vhdl_ls.py
@@ -21,7 +21,7 @@ class VhdlLanguageServer(object):
"textDocument/didChange": self.textDocument_didChange,
"textDocument/didClose": self.textDocument_didClose,
"textDocument/didSave": self.textDocument_didSave,
- # 'textDocument/hover': self.hover,
+ "textDocument/hover": self.textDocument_hover,
"textDocument/definition": self.textDocument_definition,
"textDocument/documentSymbol": self.textDocument_documentSymbol,
# 'textDocument/completion': self.completion,
@@ -50,7 +50,7 @@ class VhdlLanguageServer(object):
"change": lsp.TextDocumentSyncKind.INCREMENTAL,
"save": {"includeText": True},
},
- "hoverProvider": False,
+ "hoverProvider": True,
# 'completionProvider': False,
# 'signatureHelpProvider': {
# 'triggerCharacters': ['(', ',']
@@ -125,6 +125,9 @@ class VhdlLanguageServer(object):
self.lint(doc_uri)
return res
+ def textDocument_hover(self, textDocument=None, position=None):
+ return self.workspace.hover(textDocument["uri"], position)
+
def m_workspace__did_change_configuration(self, _settings=None):
for doc_uri in self.workspace.documents:
self.lint(doc_uri)
diff --git a/pyGHDL/lsp/workspace.py b/pyGHDL/lsp/workspace.py
index 88200bc49..fe808c23c 100644
--- a/pyGHDL/lsp/workspace.py
+++ b/pyGHDL/lsp/workspace.py
@@ -46,6 +46,8 @@ class Workspace(object):
errorout_memory.Install_Handler()
flags.Flag_Elocations.value = True
# flags.Verbose.value = True
+ # Gather comments
+ flags.Flag_Gather_Comments.value = True
# We do analysis even in case of errors.
parse.Flag_Parse_Parenthesis.value = True
# Force analysis to get more feedback + navigation even in case
@@ -393,12 +395,16 @@ class Workspace(object):
if decl_loc is None:
return None
res = [decl_loc]
+ # If the declaration is a component, also add the entity.
if nodes.Get_Kind(decl) == nodes.Iir_Kind.Component_Declaration:
ent = libraries.Find_Entity_For_Component(nodes.Get_Identifier(decl))
if ent != nodes.Null_Iir:
res.append(self.declaration_to_location(nodes.Get_Library_Unit(ent)))
return res
+ def hover(self, doc_uri, position):
+ return self._docs[doc_uri].hover(position)
+
def x_show_all_files(self):
res = []
for fe in range(1, files_map.Get_Last_Source_File_Entry() + 1):