Skip to content

Commit

Permalink
Merge pull request #246 from fortran-lang/feat/hover-types-n-mods
Browse files Browse the repository at this point in the history
feat: add hover for types and modules
  • Loading branch information
gnikit authored Dec 8, 2022
2 parents 9e5f174 + ec0271e commit 833755e
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

### Added

- Added hover messages for Types and Modules
([#208](https://github.com/fortran-lang/fortls/issues/208))
- Added support for Markdown intrinsics from the M_intrinsics repository
([#215](https://github.com/fortran-lang/fortls/issues/215))
- Added and create a schema for fortls configuration files
Expand Down
7 changes: 6 additions & 1 deletion fortls/langserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,12 @@ def create_hover(string: str, docs: str | None):
# Construct hover information
var_type: int = var_obj.get_type()
hover_array = []
if var_type in (SUBROUTINE_TYPE_ID, FUNCTION_TYPE_ID):
if var_type in (
SUBROUTINE_TYPE_ID,
FUNCTION_TYPE_ID,
MODULE_TYPE_ID,
CLASS_TYPE_ID,
):
hover_array.append(var_obj.get_hover_md(long=True))
elif var_type == INTERFACE_TYPE_ID:
for member in var_obj.mems:
Expand Down
18 changes: 17 additions & 1 deletion fortls/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,11 @@ def get_type(self, no_link=False):
def get_desc(self):
return "MODULE"

def get_hover(self, long=False, drop_arg=-1) -> tuple[str, str]:
hover = f"{self.get_desc()} {self.name}"
doc_str = self.get_documentation()
return hover, doc_str

def check_valid_parent(self):
if self.parent is not None:
return False
Expand Down Expand Up @@ -1287,7 +1292,7 @@ def __init__(
self.inherit_var = None
self.inherit_tmp = None
self.inherit_version = -1
if keywords.count(KEYWORD_ID_DICT["abstract"]) > 0:
if self.keywords.count(KEYWORD_ID_DICT["abstract"]) > 0:
self.abstract = True
else:
self.abstract = False
Expand Down Expand Up @@ -1436,6 +1441,17 @@ def get_actions(self, sline, eline):
]
return actions

def get_hover(self, long=False, drop_arg=-1) -> tuple[str, str]:
keywords = [self.get_desc()]
if self.abstract:
keywords.append("ABSTRACT")
if self.inherit:
keywords.append(f"EXTENDS({self.inherit})")
decl = ", ".join(keywords)
hover = f"{decl} :: {self.name}"
doc_str = self.get_documentation()
return hover, doc_str


class Block(Scope):
def __init__(self, file_ast: FortranAST, line_number: int, name: str):
Expand Down
70 changes: 70 additions & 0 deletions test/test_server_documentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,73 @@ def test_doc_multiline_type_bound_procedure_arg_list():
),
True,
)


def test_doxygen_doc_for_module_use():
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "docs")})
file_path = test_dir / "docs" / "test_module_and_type_doc.f90"
string += hover_request(file_path, 24, 14)
errcode, results = run_request(string)
assert errcode == 0

ref = (
(0, "```fortran90"),
(1, "MODULE doxygen_doc_mod"),
(2, "```"),
(3, "-----"),
(4, "module doc for doxygen_doc_mod"),
(5, ""),
(6, "with info"),
)
check_return(results[1], ref)


def test_ford_doc_for_module_use():
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "docs")})
file_path = test_dir / "docs" / "test_module_and_type_doc.f90"
string += hover_request(file_path, 25, 14)
errcode, results = run_request(string)
assert errcode == 0

ref = (
(0, "```fortran90"),
(1, "MODULE ford_doc_mod"),
(2, "```"),
(3, "-----"),
(4, "Doc for ford_doc_mod"),
)
check_return(results[1], ref)


def test_doxygen_doc_for_type():
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "docs")})
file_path = test_dir / "docs" / "test_module_and_type_doc.f90"
string += hover_request(file_path, 27, 11)
errcode, results = run_request(string)
assert errcode == 0

ref = (
(0, "```fortran90"),
(1, "TYPE :: a_t"),
(2, "```"),
(3, "-----"),
(4, "Doc for a_t"),
)
check_return(results[1], ref)


def test_ford_doc_for_type():
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "docs")})
file_path = test_dir / "docs" / "test_module_and_type_doc.f90"
string += hover_request(file_path, 28, 11)
errcode, results = run_request(string)
assert errcode == 0

ref = (
(0, "```fortran90"),
(1, "TYPE :: b_t"),
(2, "```"),
(3, "-----"),
(4, "Doc for b_t"),
)
check_return(results[1], ref)
17 changes: 17 additions & 0 deletions test/test_server_hover.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,3 +538,20 @@ def test_intrinsics():
intrinsics = json.load(f)
ref_results = ["\n-----\n" + intrinsics["SIZE"]]
validate_hover(results, ref_results)


def test_types():
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "hover")})
file_path = test_dir / "hover" / "types.f90"
string += hover_req(file_path, 3, 25)
string += hover_req(file_path, 6, 44)
string += hover_req(file_path, 9, 35)

errcode, results = run_request(string, fortls_args=["-n", "1"])
assert errcode == 0
ref_results = [
"```fortran90\nTYPE, ABSTRACT :: base_t\n```",
"```fortran90\nTYPE, ABSTRACT, EXTENDS(base_t) :: extends_t\n```",
"```fortran90\nTYPE, EXTENDS(extends_t) :: a_t\n```",
]
validate_hover(results, ref_results)
30 changes: 30 additions & 0 deletions test/test_source/docs/test_module_and_type_doc.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
!> module doc for doxygen_doc_mod
!!
!! with info
module doxygen_doc_mod
implicit none

!> Doc for a_t
type :: a_t
end type
end module


module ford_doc_mod
!! Doc for ford_doc_mod
implicit none

type :: b_t
!! Doc for b_t
end type

end module


program main
use doxygen_doc_mod
use ford_doc_mod

type(a_t) :: a
type(b_t) :: b
end program
12 changes: 12 additions & 0 deletions test/test_source/hover/types.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module some_mod
implicit none

type, abstract :: base_t
end type

type, abstract, extends(base_t) :: extends_t
end type

type, extends(extends_t) :: a_t
end type
end module

0 comments on commit 833755e

Please sign in to comment.