Skip to content

Commit 30c80f1

Browse files
committed
feat: Add hover info for modules and types including any docstring
Fixes #208
1 parent b4ba1cd commit 30c80f1

File tree

7 files changed

+148
-2
lines changed

7 files changed

+148
-2
lines changed

fortls/langserver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,7 @@ def create_hover(string: str, docs: str | None):
10661066
# Construct hover information
10671067
var_type: int = var_obj.get_type()
10681068
hover_array = []
1069-
if var_type in (SUBROUTINE_TYPE_ID, FUNCTION_TYPE_ID):
1069+
if var_type in (SUBROUTINE_TYPE_ID, FUNCTION_TYPE_ID, MODULE_TYPE_ID, CLASS_TYPE_ID):
10701070
hover_array.append(var_obj.get_hover_md(long=True))
10711071
elif var_type == INTERFACE_TYPE_ID:
10721072
for member in var_obj.mems:

fortls/objects.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,11 @@ def get_type(self, no_link=False):
723723
def get_desc(self):
724724
return "MODULE"
725725

726+
def get_hover(self, long=False, drop_arg=-1) -> tuple[str, str]:
727+
hover = f"{self.get_desc()} {self.name}"
728+
doc_str = self.get_documentation()
729+
return hover, doc_str
730+
726731
def check_valid_parent(self):
727732
if self.parent is not None:
728733
return False
@@ -1206,7 +1211,7 @@ def __init__(
12061211
self.inherit_var = None
12071212
self.inherit_tmp = None
12081213
self.inherit_version = -1
1209-
if keywords.count(KEYWORD_ID_DICT["abstract"]) > 0:
1214+
if self.keywords.count(KEYWORD_ID_DICT["abstract"]) > 0:
12101215
self.abstract = True
12111216
else:
12121217
self.abstract = False
@@ -1355,6 +1360,17 @@ def get_actions(self, sline, eline):
13551360
]
13561361
return actions
13571362

1363+
def get_hover(self, long=False, drop_arg=-1) -> tuple[str, str]:
1364+
keywords = [self.get_desc()]
1365+
if self.abstract:
1366+
keywords.append("ABSTRACT")
1367+
if self.inherit:
1368+
keywords.append(f"EXTENDS({self.inherit})")
1369+
decl = ", ".join(keywords)
1370+
hover = f"{decl} :: {self.name}"
1371+
doc_str = self.get_documentation()
1372+
return hover, doc_str
1373+
13581374

13591375
class Block(Scope):
13601376
def __init__(self, file_ast: FortranAST, line_number: int, name: str):

test/setup_tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def run_request(request, fortls_args: list[str] = None):
2929
"-m",
3030
"fortls",
3131
"--incremental_sync",
32+
"--disable_autoupdate"
3233
]
3334
if fortls_args:
3435
# Input args might not be sanitised, fix that

test/test_server_documentation.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,73 @@ def test_doc_multiline_type_bound_procedure_arg_list():
300300
),
301301
True,
302302
)
303+
304+
305+
def test_doxygen_doc_for_module_use():
306+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "docs")})
307+
file_path = test_dir / "docs" / "test_module_and_type_doc.f90"
308+
string += hover_request(file_path, 24, 14)
309+
errcode, results = run_request(string)
310+
assert errcode == 0
311+
312+
ref = (
313+
(0, '```fortran90'),
314+
(1, 'MODULE doxygen_doc_mod'),
315+
(2, '```'),
316+
(3, '-----'),
317+
(4, 'module doc for doxygen_doc_mod'),
318+
(5, ''),
319+
(6, 'with info'),
320+
)
321+
check_return(results[1], ref)
322+
323+
324+
def test_ford_doc_for_module_use():
325+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "docs")})
326+
file_path = test_dir / "docs" / "test_module_and_type_doc.f90"
327+
string += hover_request(file_path, 25, 14)
328+
errcode, results = run_request(string)
329+
assert errcode == 0
330+
331+
ref = (
332+
(0, '```fortran90'),
333+
(1, 'MODULE ford_doc_mod'),
334+
(2, '```'),
335+
(3, '-----'),
336+
(4, "Doc for ford_doc_mod"),
337+
)
338+
check_return(results[1], ref)
339+
340+
341+
def test_doxygen_doc_for_type():
342+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "docs")})
343+
file_path = test_dir / "docs" / "test_module_and_type_doc.f90"
344+
string += hover_request(file_path, 27, 11)
345+
errcode, results = run_request(string)
346+
assert errcode == 0
347+
348+
ref = (
349+
(0, '```fortran90'),
350+
(1, 'TYPE :: a_t'),
351+
(2, '```'),
352+
(3, '-----'),
353+
(4, "Doc for a_t"),
354+
)
355+
check_return(results[1], ref)
356+
357+
358+
def test_ford_doc_for_type():
359+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "docs")})
360+
file_path = test_dir / "docs" / "test_module_and_type_doc.f90"
361+
string += hover_request(file_path, 28, 11)
362+
errcode, results = run_request(string)
363+
assert errcode == 0
364+
365+
ref = (
366+
(0, '```fortran90'),
367+
(1, 'TYPE :: b_t'),
368+
(2, '```'),
369+
(3, '-----'),
370+
(4, "Doc for b_t"),
371+
)
372+
check_return(results[1], ref)

test/test_server_hover.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,3 +538,20 @@ def test_intrinsics():
538538
intrinsics = json.load(f)
539539
ref_results = ["\n-----\n" + intrinsics["SIZE"]]
540540
validate_hover(results, ref_results)
541+
542+
543+
def test_types():
544+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "hover")})
545+
file_path = test_dir / "hover" / "types.f90"
546+
string += hover_req(file_path, 3, 25)
547+
string += hover_req(file_path, 6, 44)
548+
string += hover_req(file_path, 9, 35)
549+
550+
errcode, results = run_request(string, fortls_args=["-n", "1"])
551+
assert errcode == 0
552+
ref_results = [
553+
"```fortran90\nTYPE, ABSTRACT :: base_t\n```",
554+
"```fortran90\nTYPE, ABSTRACT, EXTENDS(base_t) :: extends_t\n```",
555+
"```fortran90\nTYPE, EXTENDS(extends_t) :: a_t\n```",
556+
]
557+
validate_hover(results, ref_results)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
!> module doc for doxygen_doc_mod
2+
!!
3+
!! with info
4+
module doxygen_doc_mod
5+
implicit none
6+
7+
!> Doc for a_t
8+
type :: a_t
9+
end type
10+
end module
11+
12+
13+
module ford_doc_mod
14+
!! Doc for ford_doc_mod
15+
implicit none
16+
17+
type :: b_t
18+
!! Doc for b_t
19+
end type
20+
21+
end module
22+
23+
24+
program main
25+
use doxygen_doc_mod
26+
use ford_doc_mod
27+
28+
type(a_t) :: a
29+
type(b_t) :: b
30+
end program

test/test_source/hover/types.f90

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module some_mod
2+
implicit none
3+
4+
type, abstract :: base_t
5+
end type
6+
7+
type, abstract, extends(base_t) :: extends_t
8+
end type
9+
10+
type, extends(extends_t) :: a_t
11+
end type
12+
end module

0 commit comments

Comments
 (0)