Skip to content

Commit ac0b897

Browse files
committed
refactor: improve error handling in preprocessor include statement
1 parent 21a29d6 commit ac0b897

File tree

2 files changed

+33
-30
lines changed

2 files changed

+33
-30
lines changed

fortls/parsers/internal/parser.py

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99

1010
# Python < 3.8 does not have typing.Literals
1111
try:
12-
from typing import Literal
12+
from typing import Iterable, Literal
1313
except ImportError:
14-
from typing_extensions import Literal
14+
from typing_extensions import Literal, Iterable
1515

1616
from re import Match, Pattern
1717

@@ -2097,6 +2097,14 @@ def append_multiline_macro(def_value: str | tuple, line: str):
20972097
return (def_args, def_value)
20982098
return def_value + line
20992099

2100+
def find_file_in_directories(directories: Iterable[str], filename: str) -> str:
2101+
for include_dir in directories:
2102+
file = os.path.join(include_dir, filename)
2103+
if os.path.isfile(file):
2104+
return file
2105+
msg = f"Could not locate include file: {filename} in {directories}"
2106+
raise FortranFileNotFoundError(msg)
2107+
21002108
if pp_defs is None:
21012109
pp_defs = {}
21022110
if include_dirs is None:
@@ -2250,34 +2258,21 @@ def append_multiline_macro(def_value: str | tuple, line: str):
22502258
if (match is not None) and ((len(pp_stack) == 0) or (pp_stack[-1][0] < 0)):
22512259
log.debug("%s !!! Include statement(%d)", line.strip(), i + 1)
22522260
include_filename = match.group(1).replace('"', "")
2253-
include_path = None
2254-
# Intentionally keep this as a list and not a set. There are cases
2255-
# where projects play tricks with the include order of their headers
2256-
# to get their codes to compile. Using a set would not permit that.
2257-
for include_dir in include_dirs:
2258-
include_path_tmp = os.path.join(include_dir, include_filename)
2259-
if os.path.isfile(include_path_tmp):
2260-
include_path = os.path.abspath(include_path_tmp)
2261-
break
2262-
if include_path is not None:
2263-
try:
2264-
include_file = FortranFile(include_path)
2265-
include_file.load_from_disk()
2266-
log.debug("\n!!! Parsing include file '%s'", include_path)
2267-
_, _, _, defs_tmp = preprocess_file(
2268-
include_file.contents_split,
2269-
file_path=include_path,
2270-
pp_defs=defs_tmp,
2271-
include_dirs=include_dirs,
2272-
debug=debug,
2273-
)
2274-
log.debug("!!! Completed parsing include file")
2275-
except FortranFileNotFoundError as e:
2276-
log.debug("!!! Failed to parse include file: %s", str(e))
2277-
else:
2278-
log.debug(
2279-
"%s !!! Could not locate include file (%d)", line.strip(), i + 1
2261+
try:
2262+
include_path = find_file_in_directories(include_dirs, include_filename)
2263+
include_file = FortranFile(include_path)
2264+
include_file.load_from_disk()
2265+
log.debug("\n!!! Parsing include file '%s'", include_path)
2266+
_, _, _, defs_tmp = preprocess_file(
2267+
include_file.contents_split,
2268+
file_path=include_path,
2269+
pp_defs=defs_tmp,
2270+
include_dirs=include_dirs,
2271+
debug=debug,
22802272
)
2273+
log.debug("!!! Completed parsing include file")
2274+
except FortranFileNotFoundError as e:
2275+
log.debug("%s !!! %s - Ln:%d", line.strip(), str(e), i + 1)
22812276

22822277
# Substitute (if any) read in preprocessor macros
22832278
for def_tmp, value in defs_tmp.items():

test/test_parser.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import pytest
22
from setup_tests import test_dir
33

4-
from fortls.parsers.internal.parser import FortranFile, FortranFileNotFoundError
4+
from fortls.parsers.internal.parser import (
5+
FortranFile,
6+
FortranFileNotFoundError,
7+
preprocess_file,
8+
)
59

610

711
def test_line_continuations():
@@ -36,3 +40,7 @@ def test_load_from_disk_exception():
3640
file = FortranFile("/path/to/nonexistent/file.f90")
3741
with pytest.raises(FortranFileNotFoundError):
3842
file.load_from_disk()
43+
44+
45+
def test_preprocess_missing_includes_exception():
46+
preprocess_file(["#include 'nonexistent_file.f90'"])

0 commit comments

Comments
 (0)