Skip to content

Commit 6a7eae7

Browse files
zerocewlfelix.boeckelmannccordoba12
authored
Follow LSP protocol when workspace folders are changed and adapt root workspace uri if folder is changed (#754)
Co-authored-by: felix.boeckelmann <[email protected]> Co-authored-by: Carlos Cordoba <[email protected]>
1 parent 462893c commit 6a7eae7

File tree

2 files changed

+110
-9
lines changed

2 files changed

+110
-9
lines changed

pyls/python_ls.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -361,14 +361,37 @@ def m_workspace__did_change_configuration(self, settings=None):
361361
for doc_uri in workspace.documents:
362362
self.lint(doc_uri, is_saved=False)
363363

364-
def m_workspace__did_change_workspace_folders(self, added=None, removed=None, **_kwargs):
364+
def m_workspace__did_change_workspace_folders(self, event=None, **_kwargs): # pylint: disable=too-many-locals
365+
if event is None:
366+
return
367+
added = event.get('added', [])
368+
removed = event.get('removed', [])
369+
365370
for removed_info in removed:
366-
removed_uri = removed_info['uri']
367-
self.workspaces.pop(removed_uri)
371+
if 'uri' in removed_info:
372+
removed_uri = removed_info['uri']
373+
self.workspaces.pop(removed_uri, None)
368374

369375
for added_info in added:
370-
added_uri = added_info['uri']
371-
self.workspaces[added_uri] = Workspace(added_uri, self._endpoint, self.config)
376+
if 'uri' in added_info:
377+
added_uri = added_info['uri']
378+
self.workspaces[added_uri] = Workspace(added_uri, self._endpoint, self.config)
379+
380+
root_workspace_removed = any(removed_info['uri'] == self.root_uri for removed_info in removed)
381+
workspace_added = len(added) > 0 and 'uri' in added[0]
382+
if root_workspace_removed and workspace_added:
383+
added_uri = added[0]['uri']
384+
self.root_uri = added_uri
385+
self.workspace = self.workspaces[added_uri]
386+
elif root_workspace_removed:
387+
# NOTE: Removing the root workspace can only happen when the server
388+
# is closed, thus the else condition of this if can never happen.
389+
if self.workspaces:
390+
log.debug('Root workspace deleted!')
391+
available_workspaces = sorted(self.workspaces)
392+
first_workspace = available_workspaces[0]
393+
self.root_uri = first_workspace
394+
self.workspace = self.workspaces[first_workspace]
372395

373396
# Migrate documents that are on the root workspace and have a better
374397
# match now

test/test_workspace.py

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ def test_multiple_workspaces(tmpdir, pyls):
9696

9797
added_workspaces = [{'uri': path_as_uri(str(x))}
9898
for x in (workspace1_dir, workspace2_dir)]
99-
pyls.m_workspace__did_change_workspace_folders(
100-
added=added_workspaces, removed=[])
99+
event = {'added': added_workspaces, 'removed': []}
100+
pyls.m_workspace__did_change_workspace_folders(event)
101101

102102
for workspace in added_workspaces:
103103
assert workspace['uri'] in pyls.workspaces
@@ -116,6 +116,84 @@ def test_multiple_workspaces(tmpdir, pyls):
116116
workspace2_uri = added_workspaces[1]['uri']
117117
assert msg['uri'] in pyls.workspaces[workspace2_uri]._docs
118118

119-
pyls.m_workspace__did_change_workspace_folders(
120-
added=[], removed=[added_workspaces[0]])
119+
event = {'added': [], 'removed': [added_workspaces[0]]}
120+
pyls.m_workspace__did_change_workspace_folders(event)
121121
assert workspace1_uri not in pyls.workspaces
122+
123+
124+
def test_multiple_workspaces_wrong_removed_uri(pyls):
125+
workspace = {'uri': 'Test123'}
126+
event = {'added': [], 'removed': [workspace]}
127+
pyls.m_workspace__did_change_workspace_folders(event)
128+
assert workspace['uri'] not in pyls.workspaces
129+
130+
131+
def test_root_workspace_changed(pyls):
132+
test_uri = 'Test123'
133+
pyls.root_uri = test_uri
134+
pyls.workspace._root_uri = test_uri
135+
136+
workspace1 = {'uri': test_uri}
137+
workspace2 = {'uri': 'NewTest456'}
138+
139+
event = {'added': [workspace2], 'removed': [workspace1]}
140+
pyls.m_workspace__did_change_workspace_folders(event)
141+
142+
assert workspace2['uri'] == pyls.workspace._root_uri
143+
assert workspace2['uri'] == pyls.root_uri
144+
145+
146+
def test_root_workspace_not_changed(pyls):
147+
# removed uri != root_uri
148+
test_uri_1 = 'Test12'
149+
pyls.root_uri = test_uri_1
150+
pyls.workspace._root_uri = test_uri_1
151+
workspace1 = {'uri': 'Test1234'}
152+
workspace2 = {'uri': 'NewTest456'}
153+
event = {'added': [workspace2], 'removed': [workspace1]}
154+
pyls.m_workspace__did_change_workspace_folders(event)
155+
assert test_uri_1 == pyls.workspace._root_uri
156+
assert test_uri_1 == pyls.root_uri
157+
# empty 'added' list
158+
test_uri_2 = 'Test123'
159+
new_root_uri = workspace2['uri']
160+
pyls.root_uri = test_uri_2
161+
pyls.workspace._root_uri = test_uri_2
162+
workspace1 = {'uri': test_uri_2}
163+
event = {'added': [], 'removed': [workspace1]}
164+
pyls.m_workspace__did_change_workspace_folders(event)
165+
assert new_root_uri == pyls.workspace._root_uri
166+
assert new_root_uri == pyls.root_uri
167+
# empty 'removed' list
168+
event = {'added': [workspace1], 'removed': []}
169+
pyls.m_workspace__did_change_workspace_folders(event)
170+
assert new_root_uri == pyls.workspace._root_uri
171+
assert new_root_uri == pyls.root_uri
172+
# 'added' list has no 'uri'
173+
workspace2 = {'TESTuri': 'Test1234'}
174+
event = {'added': [workspace2], 'removed': [workspace1]}
175+
pyls.m_workspace__did_change_workspace_folders(event)
176+
assert new_root_uri == pyls.workspace._root_uri
177+
assert new_root_uri == pyls.root_uri
178+
179+
180+
def test_root_workspace_removed(tmpdir, pyls):
181+
workspace1_dir = tmpdir.mkdir('workspace1')
182+
workspace2_dir = tmpdir.mkdir('workspace2')
183+
root_uri = pyls.root_uri
184+
185+
# Add workspaces to the pyls
186+
added_workspaces = [{'uri': path_as_uri(str(x))}
187+
for x in (workspace1_dir, workspace2_dir)]
188+
event = {'added': added_workspaces, 'removed': []}
189+
pyls.m_workspace__did_change_workspace_folders(event)
190+
191+
# Remove the root workspace
192+
removed_workspaces = [{'uri': root_uri}]
193+
event = {'added': [], 'removed': removed_workspaces}
194+
pyls.m_workspace__did_change_workspace_folders(event)
195+
196+
# Assert that the first of the workspaces (in alphabetical order) is now
197+
# the root workspace
198+
assert pyls.root_uri == path_as_uri(str(workspace1_dir))
199+
assert pyls.workspace._root_uri == path_as_uri(str(workspace1_dir))

0 commit comments

Comments
 (0)