Skip to content

Commit

Permalink
Merge pull request #19 from gnikit/bug/4
Browse files Browse the repository at this point in the history
Fixes bug with fortan line cont and preproc
  • Loading branch information
gnikit authored Jan 17, 2022
2 parents 052f24d + f86801d commit 058cb92
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 8 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
([gnikit/fortls#16](https://github.com/gnikit/fortls/issues/16))
- Fixes `END FORALL` end of scope error
([gnikit/fortls#18](https://github.com/gnikit/fortls/issues/18))
- Fixes Fortran line continuation definitions intermingled with preprocessor directives
([#203](https://github.com/hansec/fortran-language-server/issues/203))
([gnikit/fortls#4](https://github.com/gnikit/fortls/issues/4))

## 1.16.0

Expand Down
19 changes: 12 additions & 7 deletions fortls/parse_fortran.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
NAT_VAR_REGEX,
NON_DEF_REGEX,
PARAMETER_VAL_REGEX,
PP_ANY_REGEX,
PP_DEF_REGEX,
PP_INCLUDE_REGEX,
PP_REGEX,
Expand Down Expand Up @@ -978,7 +979,7 @@ def get_code_line(
line_ind -= 1
else: # Free format file
opt_cont_match = FREE_CONT_REGEX.match(curr_line)
if opt_cont_match is not None:
if opt_cont_match:
curr_line = (
" " * opt_cont_match.end(0) + curr_line[opt_cont_match.end(0) :]
)
Expand All @@ -989,7 +990,7 @@ def get_code_line(
tmp_no_comm = tmp_line.split("!")[0]
cont_ind = tmp_no_comm.rfind("&")
opt_cont_match = FREE_CONT_REGEX.match(tmp_no_comm)
if opt_cont_match is not None:
if opt_cont_match:
if cont_ind == opt_cont_match.end(0) - 1:
break
tmp_no_comm = (
Expand Down Expand Up @@ -1022,21 +1023,27 @@ def get_code_line(
if iComm < 0:
iComm = iAmper + 1
next_line = ""
# Read the next line if needed
while (iAmper >= 0) and (iAmper < iComm):
if line_ind == line_number + 1:
curr_line = curr_line[:iAmper]
elif next_line != "":
post_lines[-1] = next_line[:iAmper]
next_line = self.get_line(line_ind, pp_content)
line_ind += 1
# Skip any preprocessor statements when seeking the next line
if PP_ANY_REGEX.match(next_line):
next_line = ""
post_lines.append("")
continue
# Skip empty or comment lines
match = FREE_COMMENT_LINE_MATCH.match(next_line)
if (next_line.rstrip() == "") or (match is not None):
if next_line.rstrip() == "" or match:
next_line = ""
post_lines.append("")
continue
opt_cont_match = FREE_CONT_REGEX.match(next_line)
if opt_cont_match is not None:
if opt_cont_match:
next_line = (
" " * opt_cont_match.end(0)
+ next_line[opt_cont_match.end(0) :]
Expand All @@ -1056,9 +1063,7 @@ def get_code_line(
def strip_comment(self, line: str) -> str:
"""Strip comment from line"""
if self.fixed:
if (FIXED_COMMENT_LINE_MATCH.match(line) is not None) and (
FIXED_OPENMP_MATCH.match(line) is not None
):
if FIXED_COMMENT_LINE_MATCH.match(line) and FIXED_OPENMP_MATCH.match(line):
return ""
else:
if FREE_OPENMP_MATCH.match(line) is None:
Expand Down
1 change: 1 addition & 0 deletions fortls/regex_patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
PP_DEF_REGEX = re.compile(r"#(define|undef)[ ]*([\w]+)(\((\w+(,[ ]*)?)+\))?", re.I)
PP_DEF_TEST_REGEX = re.compile(r"(![ ]*)?defined[ ]*\([ ]*([a-z0-9_]*)[ ]*\)$", re.I)
PP_INCLUDE_REGEX = re.compile(r"#include[ ]*([\"a-z0-9_\.]*)", re.I)
PP_ANY_REGEX = re.compile(r"(^#:?\w+)")
# Context matching rules
CALL_REGEX = re.compile(r"[ ]*CALL[ ]+[a-z0-9_%]*$", re.I)
INT_STMNT_REGEX = re.compile(r"^[ ]*[a-z]*$", re.I)
Expand Down
3 changes: 3 additions & 0 deletions test/test_preproc.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def check_return(result_array, checks):
string += hover_req(file_path, 7, 40) # multi-lin variable
string += hover_req(file_path, 8, 7) # function with if conditional
string += hover_req(file_path, 9, 7) # multiline function with if conditional
file_path = os.path.join(test_dir, "pp", "preproc_keywords.F90")
string += hover_req(file_path, 6, 2) # ignores PP across Fortran line continuations
errcode, results = run_request(string, f" --config={root_dir}/.pp_conf.json")
assert errcode == 0

Expand All @@ -44,6 +46,7 @@ def check_return(result_array, checks):
"#define varVar 55",
"#define ewrite if (priority <= 3) write((priority), format)",
"#define ewrite2 if (priority <= 3) write((priority), format)",
"REAL, CONTIGUOUS, POINTER, DIMENSION(:)",
)
assert len(ref_results) == len(results) - 1
check_return(results[1:], ref_results)
1 change: 1 addition & 0 deletions test/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ def check_return(result_array):
["test_int", 2, 0],
["test_mod", 2, 0],
["test_nonint_mod", 2, 0],
["test_preproc_keywords", 2, 0],
["test_program", 2, 0],
["test_rename_sub", 6, 9],
["test_select", 2, 0],
Expand Down
3 changes: 2 additions & 1 deletion test/test_source/pp/.pp_conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
"enable_code_actions": true,
"pp_suffixes": [".h", ".F90"],
"incl_suffixes": [".h"],
"include_dirs": ["include"]
"include_dirs": ["include"],
"pp_defs": { "HAVE_CONTIGUOUS": "" }
}
10 changes: 10 additions & 0 deletions test/test_source/pp/preproc_keywords.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
program test_preproc_keywords
REAL &
#ifdef HAVE_CONTIGUOUS
, CONTIGUOUS &
#endif
, POINTER :: &
var1(:), &
var2(:)

end program test_preproc_keywords

0 comments on commit 058cb92

Please sign in to comment.