File: associate.py

package info (click to toggle)
fortran-language-server 3.2.2%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,268 kB
  • sloc: python: 9,688; f90: 1,195; fortran: 30; makefile: 28; ansic: 20
file content (87 lines) | stat: -rw-r--r-- 3,062 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from __future__ import annotations

import re
from dataclasses import dataclass
from typing import TYPE_CHECKING

from fortls.constants import ASSOC_TYPE_ID
from fortls.helper_functions import get_var_stack

from .block import Block
from .utilities import climb_type_tree, find_in_scope
from .variable import Variable

if TYPE_CHECKING:
    from .ast import FortranAST


@dataclass
class AssociateMap:
    var: Variable
    bind_name: str
    link_name: str


class Associate(Block):
    def __init__(self, file_ast: FortranAST, line_number: int, name: str):
        super().__init__(file_ast, line_number, name)
        self.links: list[AssociateMap] = []  # holds the info to associate variables

    def get_type(self, no_link=False):
        return ASSOC_TYPE_ID

    def get_desc(self):
        return "ASSOCIATE"

    def create_binding_variable(
        self, file_ast: FortranAST, line_number: int, bind_name: str, link_name: str
    ) -> Variable:
        """Create a new variable to be linked upon resolution to the real variable
        that contains the information of the mapping from the parent scope to the
        ASSOCIATE block scope.

        Parameters
        ----------
        file_ast : fortran_ast
            AST file
        line_number : int
            Line number
        bind_name : str
            Name of the ASSOCIATE block variable
        link_name : str
            Name of the parent scope variable

        Returns
        -------
        fortran_var
            Variable object holding the ASSOCIATE block variable, pending resolution
        """
        new_var = Variable(file_ast, line_number, bind_name, "UNKNOWN", [])
        self.links.append(AssociateMap(new_var, bind_name, link_name))
        return new_var

    def resolve_link(self, obj_tree):
        # Loop through the list of the associated variables map and resolve the links
        # find the AST node that that corresponds to the variable with link_name
        for assoc in self.links:
            # TODO: extract the dimensions component from the link_name
            # re.sub(r'\(.*\)', '', link_name) removes the dimensions component
            # keywords = re.match(r'(.*)\((.*)\)', link_name).groups()
            # now pass the keywords through the dimension_parser and set the keywords
            # in the associate object. Hover should now pick the local keywords
            # over the linked_object keywords
            assoc.link_name = re.sub(r"\(.*\)", "", assoc.link_name)
            var_stack = get_var_stack(assoc.link_name)
            is_member = len(var_stack) > 1
            if is_member:
                type_scope = climb_type_tree(var_stack, self, obj_tree)
                if type_scope is None:
                    continue
                var_obj = find_in_scope(type_scope, var_stack[-1], obj_tree)
            else:
                var_obj = find_in_scope(self, assoc.link_name, obj_tree)
            if var_obj is not None:
                assoc.var.link_obj = var_obj

    def require_link(self):
        return True