Skip to content

Commit 4d3effe

Browse files
committed
feat: adds full support for import host assoc
There is some polishing of the code that is required but this is mostly done.
1 parent b4fa690 commit 4d3effe

File tree

5 files changed

+251
-103
lines changed

5 files changed

+251
-103
lines changed

fortls/intrinsics.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
Module,
1313
Subroutine,
1414
Type,
15+
Use,
1516
Variable,
1617
)
1718

@@ -119,7 +120,7 @@ def create_object(json_obj: dict, enc_obj=None):
119120
if json_obj["type"] == 0: # module, match "type": in JSON files
120121
mod_tmp = Module(intrinsic_ast, 0, name)
121122
if "use" in json_obj:
122-
mod_tmp.add_use(json_obj["use"], 0)
123+
mod_tmp.add_use(Use(json_obj["use"], line_number=0))
123124
return mod_tmp
124125
elif json_obj["type"] == 1: # subroutine, match "type": in JSON files
125126
return Subroutine(intrinsic_ast, 0, name, args=args)

fortls/langserver.py

Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
from fortls.jsonrpc import JSONRPC2Connection, path_from_uri, path_to_uri
5252
from fortls.objects import (
5353
FortranAST,
54+
Import,
55+
Scope,
56+
Use,
5457
Variable,
5558
climb_type_tree,
5659
find_in_scope,
@@ -386,7 +389,10 @@ def get_candidates(
386389
):
387390
#
388391
def child_candidates(
389-
scope, only_list: list = None, filter_public=True, req_abstract=False
392+
scope: Scope,
393+
only_list: list = None,
394+
filter_public=True,
395+
req_abstract=False,
390396
):
391397
if only_list is None:
392398
only_list = []
@@ -411,7 +417,7 @@ def child_candidates(
411417
return tmp_list
412418

413419
var_list = []
414-
use_dict = {}
420+
use_dict: dict[str, Use | Import] = {}
415421
for scope in scope_list:
416422
var_list += child_candidates(
417423
scope, filter_public=public_only, req_abstract=abstract_only
@@ -421,48 +427,64 @@ def child_candidates(
421427
use_dict = get_use_tree(scope, use_dict, self.obj_tree)
422428
# Look in found use modules
423429
rename_list = [None for _ in var_list]
430+
import_var_list = []
424431
for use_mod, use_info in use_dict.items():
425-
scope = self.obj_tree[use_mod][0]
426-
only_list = use_info.only_list
427-
if len(use_info.rename_map) > 0:
428-
only_list = [
429-
use_info.rename_map.get(only_name, only_name)
430-
for only_name in only_list
431-
]
432-
tmp_list = child_candidates(
433-
scope, only_list, req_abstract=abstract_only
434-
)
435-
# Setup renaming
436-
if len(use_info.rename_map) > 0:
437-
rename_reversed = {
438-
value: key for (key, value) in use_info.rename_map.items()
439-
}
440-
for tmp_obj in tmp_list:
441-
var_list.append(tmp_obj)
442-
rename_list.append(
443-
rename_reversed.get(tmp_obj.name.lower(), None)
444-
)
445-
else:
446-
var_list += tmp_list
447-
rename_list += [None for _ in tmp_list]
432+
if type(use_info) is Use:
433+
scope = self.obj_tree[use_mod][0]
434+
only_list = use_info.only_list
435+
if use_info.rename_map:
436+
only_list = [
437+
use_info.rename_map.get(only_name, only_name)
438+
for only_name in only_list
439+
]
440+
# TODO: replace only_name -> with use_info.rename()
441+
tmp_list = child_candidates(
442+
scope, only_list, req_abstract=abstract_only
443+
)
444+
# Setup renaming
445+
if use_info.rename_map:
446+
rename_reversed = {
447+
value: key for (key, value) in use_info.rename_map.items()
448+
}
449+
for tmp_obj in tmp_list:
450+
var_list.append(tmp_obj)
451+
rename_list.append(
452+
rename_reversed.get(tmp_obj.name.lower(), None)
453+
)
454+
else:
455+
var_list += tmp_list
456+
rename_list += [None for _ in tmp_list]
457+
elif type(use_info) is Import:
458+
scope = use_info.scope
459+
# Add import candidates
460+
import_var_list += child_candidates(
461+
scope,
462+
only_list=use_info.only_list,
463+
req_abstract=abstract_only,
464+
)
465+
# We do not have renames so ignore
466+
448467
# Add globals
449468
if inc_globals:
450469
tmp_list = [obj[0] for (_, obj) in self.obj_tree.items()]
451470
var_list += tmp_list + self.intrinsic_funs
452471
rename_list += [None for _ in tmp_list + self.intrinsic_funs]
472+
if import_var_list:
473+
var_list = import_var_list
474+
rename_list = [None for _ in import_var_list]
453475
# Filter by prefix if necessary
454476
if var_prefix == "":
455477
return var_list, rename_list
456478
else:
457479
tmp_list = []
458480
tmp_rename = []
459-
for (i, var) in enumerate(var_list):
460-
var_name = rename_list[i]
481+
for (var, rename) in zip(var_list, rename_list):
482+
var_name = rename
461483
if var_name is None:
462484
var_name = var.name
463485
if var_name.lower().startswith(var_prefix):
464486
tmp_list.append(var)
465-
tmp_rename.append(rename_list[i])
487+
tmp_rename.append(rename)
466488
return tmp_list, tmp_rename
467489

468490
def build_comp(
@@ -651,15 +673,15 @@ def build_comp(
651673
candidate_list, rename_list = get_candidates(
652674
scope_list, var_prefix, include_globals, public_only, abstract_only, no_use
653675
)
654-
for (i, candidate) in enumerate(candidate_list):
676+
for (candidate, rename) in zip(candidate_list, rename_list):
655677
# Skip module names (only valid in USE)
656678
candidate_type = candidate.get_type()
657679
if type_mask[candidate_type]:
658680
continue
659681
if req_callable and (not candidate.is_callable()):
660682
continue
661683
#
662-
name_replace = rename_list[i]
684+
name_replace = rename
663685
if candidate_type == INTERFACE_TYPE_ID and not line_context == "mod_mems":
664686
tmp_list = []
665687
if name_replace is None:

0 commit comments

Comments
 (0)