Skip to content

Commit cb78f87

Browse files
committed
Moves documentation tests to separate file
Also adds Doxygen and FORD traditional style tests instead of edge cases
1 parent c1e723f commit cb78f87

File tree

5 files changed

+214
-55
lines changed

5 files changed

+214
-55
lines changed

test/test_server.py

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -675,57 +675,3 @@ def check_return(result_array, checks):
675675
)
676676
assert len(ref_results) == len(results) - 1
677677
check_return(results[1:], ref_results)
678-
679-
680-
def test_docs():
681-
def check_return(result_array, checks):
682-
comm_lines = []
683-
for (i, hover_line) in enumerate(
684-
result_array["contents"][0]["value"].splitlines()
685-
):
686-
if hover_line.count("!!") > 0:
687-
comm_lines.append((i, hover_line))
688-
assert len(comm_lines) == len(checks)
689-
for i in range(len(checks)):
690-
assert comm_lines[i][0] == checks[i][0]
691-
assert comm_lines[i][1] == checks[i][1]
692-
693-
def hover_request(file_path, line, char):
694-
return write_rpc_request(
695-
1,
696-
"textDocument/hover",
697-
{
698-
"textDocument": {"uri": str(file_path)},
699-
"position": {"line": line, "character": char},
700-
},
701-
)
702-
703-
#
704-
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
705-
file_path = test_dir / "subdir" / "test_free.f90"
706-
string += hover_request(file_path, 13, 19)
707-
string += hover_request(file_path, 13, 31)
708-
string += hover_request(file_path, 14, 17)
709-
string += hover_request(file_path, 14, 28)
710-
string += hover_request(file_path, 21, 18)
711-
string += hover_request(file_path, 21, 37)
712-
string += hover_request(file_path, 22, 17)
713-
string += hover_request(file_path, 22, 32)
714-
string += hover_request(file_path, 15, 32)
715-
string += hover_request(file_path, 15, 47)
716-
errcode, results = run_request(string, ["-n", "1"])
717-
assert errcode == 0
718-
#
719-
check_return(results[1], ((1, "!! Doc 1"), (3, " !! Doc 5")))
720-
check_return(results[2], ((1, "!! Doc 4"), (4, " !! Doc 5")))
721-
check_return(results[3], ((1, "!! Doc 2"),))
722-
check_return(results[4], ((1, "!! Doc 6"),))
723-
check_return(results[5], ((1, "!! Doc 7"), (3, " !! Doc 8")))
724-
check_return(results[6], ((1, "!! Doc 7"), (4, " !! Doc 8")))
725-
check_return(results[7], ((1, "!! Doc 3"),))
726-
check_return(results[8], ())
727-
check_return(results[9], ((2, " !! Doc 9"), (3, " !! Doc 10")))
728-
check_return(
729-
results[10],
730-
((2, " !! Doc 9"), (3, " !! Doc 10"), (5, " !! Doc 11"), (6, " !! Doc 12")),
731-
)

test/test_server_documentation.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
from setup_tests import run_request, test_dir, write_rpc_request
2+
3+
4+
def check_return(result_array, checks):
5+
comm_lines = []
6+
for (i, hover_line) in enumerate(result_array["contents"][0]["value"].splitlines()):
7+
if hover_line.count("!!") > 0:
8+
comm_lines.append((i, hover_line))
9+
assert len(comm_lines) == len(checks)
10+
for i in range(len(checks)):
11+
assert comm_lines[i][0] == checks[i][0]
12+
assert comm_lines[i][1] == checks[i][1]
13+
14+
15+
def hover_request(file_path, line, char):
16+
return write_rpc_request(
17+
1,
18+
"textDocument/hover",
19+
{
20+
"textDocument": {"uri": str(file_path)},
21+
"position": {"line": line, "character": char},
22+
},
23+
)
24+
25+
26+
def test_doxygen():
27+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "docs")})
28+
file_path = test_dir / "docs" / "test_doxygen.f90"
29+
string += hover_request(file_path, 15, 17)
30+
errcode, results = run_request(string)
31+
assert errcode == 0
32+
ref = (
33+
(1, "!! @brief inserts a value into an ordered array"),
34+
(2, "!! "),
35+
(
36+
3,
37+
'!! An array "list" consisting of n ascending ordered values. The method'
38+
" insert a",
39+
),
40+
(4, '!! "new_entry" into the array.'),
41+
(5, "!! hint: use cshift and eo-shift"),
42+
(6, "!! "),
43+
(7, "!! @param[in,out] list a real array, size: max_size"),
44+
(8, "!! @param[in] n current values in the array"),
45+
(9, "!! @param[in] max_size size if the array"),
46+
(10, "!! @param[in] new_entry the value to insert"),
47+
)
48+
check_return(results[1], ref)
49+
50+
51+
def test_ford():
52+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "docs")})
53+
file_path = test_dir / "docs" / "test_ford.f90"
54+
string += hover_request(file_path, 5, 20)
55+
errcode, results = run_request(string)
56+
assert errcode == 0
57+
ref = (
58+
(1, "!! Feeds your cats and dogs, if enough food is available. If not enough"),
59+
(2, "!! food is available, some of your pets will get angry."),
60+
(4, " !! The number of cats to keep track of."),
61+
(6, " !! The number of dogs to keep track of."),
62+
(8, " !! The amount of pet food (in kilograms) which you have on hand."),
63+
(10, " !! The number of pets angry because they weren't fed."),
64+
)
65+
check_return(results[1], ref)
66+
67+
68+
def test_doc_overwrite_type_bound_procedure_sub():
69+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
70+
file_path = test_dir / "subdir" / "test_free.f90"
71+
# Test we can override method docstring e.g.
72+
# procedure :: name => name_imp !< Doc override
73+
# We want to preserve the argument list docstring
74+
string += hover_request(file_path, 13, 19)
75+
errcode, results = run_request(string)
76+
assert errcode == 0
77+
check_return(results[1], ((1, "!! Doc 1"), (3, " !! Doc 5")))
78+
79+
80+
def test_doc_type_bound_procedure_sub_implementation():
81+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
82+
file_path = test_dir / "subdir" / "test_free.f90"
83+
# procedure :: name => name_imp !< Doc override
84+
# Test that name_imp will yield the full docstring present in the implementation
85+
string += hover_request(file_path, 13, 31)
86+
errcode, results = run_request(string)
87+
assert errcode == 0
88+
check_return(results[1], ((1, "!! Doc 4"), (4, " !! Doc 5")))
89+
90+
91+
def test_doc_overwrite_type_bound_procedure_fun():
92+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
93+
file_path = test_dir / "subdir" / "test_free.f90"
94+
# Test we can override function docstring e.g.
95+
# procedure :: name => name_imp !< Doc override
96+
# We want to preserve the argument list docstring
97+
string += hover_request(file_path, 14, 17)
98+
errcode, results = run_request(string)
99+
assert errcode == 0
100+
check_return(results[1], ((1, "!! Doc 2"),))
101+
102+
103+
def test_doc_type_bound_procedure_fun_implementation():
104+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
105+
file_path = test_dir / "subdir" / "test_free.f90"
106+
# procedure :: name => name_imp !< Doc override
107+
# Test that name_imp will yield the full docstring present in the implementation
108+
string += hover_request(file_path, 14, 28)
109+
errcode, results = run_request(string)
110+
assert errcode == 0
111+
check_return(results[1], ((1, "!! Doc 6"),))
112+
113+
114+
def test_doc_empty_overwrite_type_bound_procedure_sub():
115+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
116+
file_path = test_dir / "subdir" / "test_free.f90"
117+
# Test we can ignore overriding method docstring and return the original e.g.
118+
# procedure :: name => name_imp !<
119+
# We want to preserve the argument list docstring
120+
string += hover_request(file_path, 21, 18)
121+
string += hover_request(file_path, 21, 37)
122+
errcode, results = run_request(string)
123+
assert errcode == 0
124+
check_return(results[1], ((1, "!! Doc 7"), (3, " !! Doc 8")))
125+
check_return(results[2], ((1, "!! Doc 7"), (4, " !! Doc 8")))
126+
127+
128+
def test_doc_empty_overwrite_type_bound_procedure_fun():
129+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
130+
file_path = test_dir / "subdir" / "test_free.f90"
131+
# procedure :: name => name_imp !< Doc
132+
# We want to preserve the procedure docstring but also fetch the empty
133+
# docs for the implementation
134+
string += hover_request(file_path, 22, 17)
135+
string += hover_request(file_path, 22, 32)
136+
errcode, results = run_request(string)
137+
assert errcode == 0
138+
check_return(results[1], ((1, "!! Doc 3"),))
139+
check_return(results[2], ())
140+
141+
142+
def test_doc_multiline_type_bound_procedure_arg_list():
143+
string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
144+
file_path = test_dir / "subdir" / "test_free.f90"
145+
# Check that inline docstrings can be input and carried over in multiple lines
146+
# for both the procedure pointer and the implementation
147+
string += hover_request(file_path, 15, 32)
148+
string += hover_request(file_path, 15, 47)
149+
errcode, results = run_request(string)
150+
assert errcode == 0
151+
check_return(results[1], ((2, " !! Doc 9"), (3, " !! Doc 10")))
152+
check_return(
153+
results[2],
154+
((2, " !! Doc 9"), (3, " !! Doc 10"), (5, " !! Doc 11"), (6, " !! Doc 12")),
155+
)

test/test_source/.fortls

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
],
55
"excl_paths": [
66
"excldir/**",
7-
"./diag/"
7+
"./diag/",
8+
"docs"
89
]
910

1011
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
module test_doxygen
2+
implicit none
3+
4+
contains
5+
6+
!> @brief inserts a value into an ordered array
7+
!!
8+
!! An array "list" consisting of n ascending ordered values. The method insert a
9+
!! "new_entry" into the array.
10+
!! hint: use cshift and eo-shift
11+
!!
12+
!! @param[in,out] list a real array, size: max_size
13+
!! @param[in] n current values in the array
14+
!! @param[in] max_size size if the array
15+
!! @param[in] new_entry the value to insert
16+
subroutine insert(list, n, max_size, new_entry)
17+
real, dimension (:), intent (inout) :: list
18+
integer, intent (in) :: n, max_size
19+
real, intent (in) :: new_entry
20+
end subroutine insert
21+
22+
!> @brief calcs the angle between two given vectors
23+
!!
24+
!! using the standard formula:
25+
!! \f$\cos \theta = \frac{ \vec v \cdot \vec w}{\abs{v}\abs{w}}\f$.
26+
!!
27+
!! @param[in] \f$v,w\f$ real vectors
28+
!! @return a real value describing the angle. 0 if \f$\abs v\f$ or \f$\abs w\f$ below a
29+
!! threshold.
30+
pure function calc_angle(v, w) result (theta)
31+
real, dimension (:), intent (in) :: v, w
32+
real :: theta
33+
end function calc_angle
34+
35+
end module test_doxygen
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module test_fortd
2+
implicit none
3+
4+
contains
5+
6+
subroutine feed_pets(cats, dogs, food, angry)
7+
!! Feeds your cats and dogs, if enough food is available. If not enough
8+
!! food is available, some of your pets will get angry.
9+
10+
! Arguments
11+
integer, intent(in) :: cats
12+
!! The number of cats to keep track of.
13+
integer, intent(in) :: dogs
14+
!! The number of dogs to keep track of.
15+
real, intent(inout) :: food
16+
!! The amount of pet food (in kilograms) which you have on hand.
17+
integer, intent(out) :: angry
18+
!! The number of pets angry because they weren't fed.
19+
20+
return
21+
end subroutine feed_pets
22+
end module test_fortd

0 commit comments

Comments
 (0)