File: test_server_rename.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 (201 lines) | stat: -rw-r--r-- 7,861 bytes parent folder | download | duplicates (2)
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
from setup_tests import (
    check_post_msg,
    path_to_uri,
    run_request,
    test_dir,
    write_rpc_request,
)


def rename_request(new_name: str, file_path, ln: int, ch: int):
    return write_rpc_request(
        1,
        "textDocument/rename",
        {
            "newName": new_name,
            "textDocument": {"uri": str(file_path)},
            "position": {"line": ln, "character": ch},
        },
    )


def check_rename_response(response: dict, references: dict):
    # Loop over URI's if the change spans multiple files there will be more than 1
    for uri, changes in response.items():
        refs = references[uri]
        # Loop over all the changes in the current URI, instances of object
        for c, r in zip(changes, refs):
            assert c["range"] == r["range"]
            assert c["newText"] == r["newText"]


def create(new_text: str, sln: int, sch: int, eln: int, ech: int):
    return {
        "range": {
            "start": {"line": sln, "character": sch},
            "end": {"line": eln, "character": ech},
        },
        "newText": new_text,
    }


def test_rename_var():
    """ "Test simple variable rename"""
    string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
    file_path = test_dir / "test_prog.f08"
    string += rename_request("str_rename", file_path, 5, 25)
    errcode, results = run_request(string)
    assert errcode == 0
    ref = {}
    ref[path_to_uri(str(file_path))] = [create("str_rename", 5, 20, 5, 29)]
    check_rename_response(results[1]["changes"], ref)


def test_rename_var_across_module():
    """Test renaming objects like variables across modules works"""
    string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
    file_path = test_dir / "test_prog.f08"
    string += rename_request("new_module_var", file_path, 26, 15)
    errcode, results = run_request(string)
    assert errcode == 0
    ref = {}
    ref[path_to_uri(str(test_dir / "subdir" / "test_free.f90"))] = [
        create("new_module_var", 32, 11, 32, 26)
    ]
    ref[path_to_uri(str(file_path))] = [create("new_module_var", 2, 44, 2, 59)]
    ref[path_to_uri(str(file_path))].append(create("new_module_var", 26, 8, 26, 23))

    check_rename_response(results[1]["changes"], ref)


def test_rename_empty():
    """Test that renaming nothing will not error"""
    string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "rename")})
    file_path = test_dir / "rename" / "test_rename_imp_type_bound_proc.f90"
    string += rename_request("bar", file_path, 9, 0)
    errcode, results = run_request(string, ["-n", "1"])
    assert errcode == 0
    assert results[1] is None


def test_rename_member_type_ptr():
    """Test that renaming type bound pointers of procedure methods rename
    only the pointer and not the implementation, even if the pointer and the
    implementation share the same name
    """
    string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
    file_path = test_dir / "test_prog.f08"
    string += rename_request("bp_rename", file_path, 18, 25)
    errcode, results = run_request(string)
    assert errcode == 0
    ref = {}
    ref[path_to_uri(str(file_path))] = [create("bp_rename", 18, 16, 18, 26)]
    ref[path_to_uri(str(test_dir / "subdir" / "test_free.f90"))] = [
        create("bp_rename", 15, 27, 15, 37)
    ]
    check_rename_response(results[1]["changes"], ref)


def test_rename_member_type_ptr_null():
    """Test renaming type bound pointers of procedure methods works when pointing to
    null
    """
    string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
    file_path = test_dir / "test_prog.f08"
    string += rename_request("bp_rename", file_path, 17, 25)
    errcode, results = run_request(string)
    assert errcode == 0
    ref = {}
    ref[path_to_uri(str(file_path))] = [create("bp_rename", 17, 16, 17, 28)]
    ref[path_to_uri(str(test_dir / "subdir" / "test_free.f90"))] = [
        create("bp_rename", 11, 43, 11, 55)
    ]
    check_rename_response(results[1]["changes"], ref)


def test_rename_type_bound_proc_no_ptr():
    """Test renaming type bound pointers of procedure methods works when no pointer
    is setup. Requesting to rename the procedure should rename, the implementation
    and the Method itself i.e. call self%foo()

    Requesting to rename the implementation should also rename the procedure
    and all the locations it is called in
    """
    root = test_dir / "rename"
    string = write_rpc_request(1, "initialize", {"rootPath": str(root)})
    file_path = root / "test_rename_imp_type_bound_proc.f90"
    # Rename the procedure name and check if implementation also renames
    string += rename_request("bar", file_path, 5, 23)
    # Rename the implementation name and check if declaration, references change
    string += rename_request("bar", file_path, 10, 18)
    errcode, results = run_request(string)
    assert errcode == 0
    ref = {}
    ref[path_to_uri(str(file_path))] = [create("bar", 5, 21, 5, 24)]
    ref[path_to_uri(str(file_path))].append(create("bar", 10, 15, 10, 18))
    ref[path_to_uri(str(file_path))].append(create("bar", 12, 18, 12, 21))
    ref[path_to_uri(str(file_path))].append(create("bar", 13, 19, 13, 22))
    check_rename_response(results[1]["changes"], ref)
    check_rename_response(results[2]["changes"], ref)


def test_rename_non_existent_file():
    """Test renaming type bound pointers of procedure methods works when pointing to
    null
    """
    string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir)})
    file_path = test_dir / "fake.f90"
    string += rename_request("bar", file_path, 5, 23)
    errcode, results = run_request(string)
    assert errcode == 0
    assert results[1] is None


def test_rename_nested():
    """Test renaming heavily nested constructs works"""
    string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "rename")})
    file_path = test_dir / "rename" / "test_rename_nested.f90"
    string += rename_request("bar", file_path, 6, 23)
    errcode, results = run_request(string, ["-n", "1"])
    assert errcode == 0
    ref = {}
    ref[path_to_uri(str(file_path))] = [create("bar", 6, 23, 6, 26)]
    ref[path_to_uri(str(file_path))].append(create("bar", 9, 27, 9, 30))
    check_rename_response(results[1]["changes"], ref)


def test_rename_intrinsic():
    """Test renaming an intrinsic function, while no other function exists
    with the same name, will throw an error
    """
    string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "rename")})
    file_path = test_dir / "rename" / "test_rename_nested.f90"
    string += rename_request("bar", file_path, 8, 27)
    errcode, results = run_request(string, ["-n", "1"])
    assert errcode == 0
    check_post_msg(results[1], "Rename failed: Cannot rename intrinsics", 2)
    assert results[2] is None


def test_rename_use_only_rename():
    """Test renaming constructs of `use mod, only: val => root_val
    are handled correctly
    """
    string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "subdir")})
    file_path = test_dir / "subdir" / "test_rename.F90"
    string += rename_request("bar", file_path, 13, 5)
    errcode, results = run_request(string, ["-n", "1"])
    # FIXME: to be implemented
    assert errcode == 0


def test_rename_skip_intrinsic():
    """Test that renaming functions named the same as intrinsic functions e.g. size()
    will only rename the user defined functions
    """
    string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "rename")})
    file_path = test_dir / "rename" / "test_rename_intrinsic.f90"
    string += rename_request("bar", file_path, 22, 13)
    errcode, results = run_request(string, ["-n", "1"])
    # FIXME: to be implemented
    assert errcode == 0