diff --git a/fortls/parsers/internal/utilities.py b/fortls/parsers/internal/utilities.py index ab41c6b5..c9acbc6a 100644 --- a/fortls/parsers/internal/utilities.py +++ b/fortls/parsers/internal/utilities.py @@ -3,7 +3,7 @@ import contextlib from typing import TYPE_CHECKING -from fortls.constants import MODULE_TYPE_ID +from fortls.constants import ENUM_TYPE_ID, MODULE_TYPE_ID from .imports import Import, ImportTypes from .use import Use @@ -141,7 +141,7 @@ def check_scope( from .function import Function for child in local_scope.get_children(): - if child.name.startswith("#GEN_INT"): + if child.name.startswith("#GEN_INT") or child.get_type() == ENUM_TYPE_ID: tmp_var = check_scope(child, var_name_lower, filter_public) if tmp_var is not None: return tmp_var diff --git a/fortls/regex_patterns.py b/fortls/regex_patterns.py index 46cc5d28..11655fe9 100644 --- a/fortls/regex_patterns.py +++ b/fortls/regex_patterns.py @@ -81,7 +81,7 @@ class FortranRegularExpressions: VAR: Pattern = compile( r"[ ]*(INTEGER|REAL|DOUBLE[ ]*PRECISION|COMPLEX" r"|DOUBLE[ ]*COMPLEX|CHARACTER|LOGICAL|PROCEDURE" - r"|EXTERNAL|CLASS|TYPE)", # external :: variable is handled by this + r"|EXTERNAL|CLASS|TYPE|ENUMERATOR)", # external :: variable is handled by this I, ) KIND_SPEC: Pattern = compile(r"[ ]*([*]?\([ ]*[\w*:]|\*[ ]*[0-9:]*)", I) diff --git a/test/test_parser.py b/test/test_parser.py index 21488ff5..bd578ca9 100644 --- a/test/test_parser.py +++ b/test/test_parser.py @@ -2,6 +2,7 @@ from setup_tests import test_dir from fortls.parsers.internal.parser import FortranFile +from fortls.parsers.internal.utilities import find_in_scope def test_line_continuations(): @@ -60,6 +61,21 @@ def test_weird_parser_bug(): assert not ast.end_errors +def test_find_in_scope_recurses_into_enum_block(): + file_path = test_dir / "test_enum_ref.f90" + file = FortranFile(str(file_path)) + err_str, _ = file.load_from_disk() + assert err_str is None + + ast = file.parse() + scope = ast.get_inner_scope(9) + assert scope is not None + result = find_in_scope(scope, "blue", {}) + + assert result is not None + assert result.name == "blue" + + @pytest.mark.parametrize( "ln_no, pp_defs, reference", [ diff --git a/test/test_server_definitions.py b/test/test_server_definitions.py index c77e93a6..258c0323 100644 --- a/test/test_server_definitions.py +++ b/test/test_server_definitions.py @@ -212,3 +212,16 @@ def test_def_function_implicit_result_variable(): assert len(ref_res) == len(results) - 1 for i, res in enumerate(ref_res): validate_def(results[i + 1], res) + + +def test_def_enumerator(): + """Test that going to definition on an enum member works.""" + string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)}) + file_path = test_dir / "test_enum_ref.f90" + string += def_request(file_path, 9, 11) + errcode, results = run_request(string) + assert errcode == 0 + ref_res = [[4, 4, str(file_path)]] + assert len(ref_res) == len(results) - 1 + for i, res in enumerate(ref_res): + validate_def(results[i + 1], res) diff --git a/test/test_server_references.py b/test/test_server_references.py index 14b0ee18..386b92de 100644 --- a/test/test_server_references.py +++ b/test/test_server_references.py @@ -75,3 +75,19 @@ def test_references_ignore_comments_on_use_import(): [str(file_path), 5, 23, 35], ), ) + + +def test_references_enumerator(): + string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)}) + file_path = test_dir / "test_enum_ref.f90" + string += ref_req(file_path, 9, 11) + errcode, results = run_request(string) + assert errcode == 0 + validate_refs( + results[1], + ( + [str(file_path), 4, 27, 31], + [str(file_path), 8, 10, 14], + [str(file_path), 9, 15, 19], + ), + ) diff --git a/test/test_source/test_enum_ref.f90 b/test/test_source/test_enum_ref.f90 new file mode 100644 index 00000000..940db22b --- /dev/null +++ b/test/test_source/test_enum_ref.f90 @@ -0,0 +1,11 @@ +program enum_refs + implicit none + + enum, bind(c) + enumerator :: red = 1, blue = 2, green = 3 + end enum + + integer :: color + color = blue + if (color == blue) color = red +end program enum_refs