Skip to content

Commit b7fb666

Browse files
committed
Add test_implementation based on test_definition
These don't work because Rope's find_implementations doesn't take a `source` argument (unlike e.g. `code_assist`) and hence *always* loads the file from disk, which means we can't use a "fake" module unless we want to use `unittest.mock.patch` to override some of this behavior, which is hacky & bad.
1 parent 84cb3a5 commit b7fb666

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

test/plugins/test_implementations.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Copyright 2017-2020 Palantir Technologies, Inc.
2+
# Copyright 2021- Python Language Server Contributors.
3+
4+
import os
5+
6+
import pytest
7+
8+
from pylsp import uris
9+
from pylsp.plugins.rope_implementation import pylsp_implementations
10+
from pylsp.workspace import Document
11+
12+
DOC_URI = uris.from_fs_path(__file__)
13+
DOC = """
14+
from abc import ABC, abstractmethod
15+
16+
class Animal(ABC):
17+
@abstractmethod
18+
def breathe(self):
19+
...
20+
21+
@property
22+
@abstractmethod
23+
def size(self) -> str:
24+
...
25+
26+
class WingedAnimal(Animal):
27+
@abstractmethod
28+
def fly(self, destination):
29+
...
30+
31+
class Bird(WingedAnimal):
32+
def breathe(self):
33+
print("*inhales like a bird*")
34+
35+
def fly(self, destination):
36+
print("*flies like a bird*")
37+
38+
@property
39+
def size(self) -> str:
40+
return "bird-sized"
41+
42+
print("not a method at all")
43+
"""
44+
45+
46+
def test_implementations(config, workspace) -> None:
47+
# Over 'fly' in WingedAnimal.fly
48+
cursor_pos = {"line": 15, "character": 9}
49+
50+
# The implementation of 'Bird.fly'
51+
def_range = {
52+
"start": {"line": 22, "character": 0},
53+
"end": {"line": 22, "character": 999},
54+
}
55+
56+
workspace.put_document(DOC_URI, DOC)
57+
doc = workspace.get_document(DOC_URI)
58+
assert [{"uri": DOC_URI, "range": def_range}] == pylsp_implementations(
59+
config, workspace, doc, cursor_pos
60+
)
61+
62+
63+
def test_implementations_skipping_one_class(config, workspace) -> None:
64+
# Over 'Animal.breathe'
65+
cursor_pos = {"line": 15, "character": 9}
66+
67+
# The implementation of 'breathe', skipping intermediate classes
68+
def_range = {
69+
"start": {"line": 19, "character": 0},
70+
"end": {"line": 19, "character": 999},
71+
}
72+
73+
doc = Document(DOC_URI, workspace, DOC)
74+
assert [{"uri": DOC_URI, "range": def_range}] == pylsp_implementations(
75+
config, workspace, doc, cursor_pos
76+
)
77+
78+
79+
@pytest.mark.xfail(reason="not implemented upstream (Rope)", strict=True)
80+
def test_property_implementations(config, workspace) -> None:
81+
# Over 'Animal.size'
82+
cursor_pos = {"line": 10, "character": 9}
83+
84+
# The property implementation 'Bird.size'
85+
def_range = {
86+
"start": {"line": 26, "character": 0},
87+
"end": {"line": 26, "character": 999},
88+
}
89+
90+
doc = Document(DOC_URI, workspace, DOC)
91+
assert [{"uri": DOC_URI, "range": def_range}] == pylsp_implementations(
92+
config, workspace, doc, cursor_pos
93+
)
94+
95+
96+
def test_no_implementations_if_not_a_method(config, workspace) -> None:
97+
# Over 'print(...)' call
98+
cursor_pos = {"line": 26, "character": 0}
99+
100+
doc = Document(DOC_URI, workspace, DOC)
101+
assert [] == pylsp_implementations(config, workspace, doc, cursor_pos)
102+
103+
104+
def test_document_path_implementations(
105+
config, workspace, workspace_other_root_path, tmpdir
106+
) -> None:
107+
# Create a dummy module out of the workspace's root_path and try to get
108+
# a implementation on it in another file placed next to it.
109+
module_content = """
110+
class A:
111+
def f():
112+
"""
113+
114+
p = tmpdir.join("mymodule.py")
115+
p.write(module_content)
116+
117+
# Content of doc to test implementation
118+
doc_content = """
119+
from mymodule import A
120+
class B(A):
121+
def f():
122+
"""
123+
doc_path = str(tmpdir) + os.path.sep + "myfile.py"
124+
doc_uri = uris.from_fs_path(doc_path)
125+
doc = Document(doc_uri, workspace_other_root_path, doc_content)
126+
127+
# The range where f is defined in mymodule.py
128+
def_range = {
129+
"start": {"line": 2, "character": 0},
130+
"end": {"line": 2, "character": 999},
131+
}
132+
133+
# The position where foo is called in myfile.py
134+
cursor_pos = {"line": 3, "character": 9}
135+
136+
# The uri for mymodule.py
137+
module_path = str(p)
138+
module_uri = uris.from_fs_path(module_path)
139+
140+
assert [{"uri": module_uri, "range": def_range}] == pylsp_implementations(
141+
config, workspace, doc, cursor_pos
142+
)

0 commit comments

Comments
 (0)