Skip to content

Commit

Permalink
Follow LSP protocol when workspace folders are changed and adapt root…
Browse files Browse the repository at this point in the history
… workspace uri if folder is changed (#754)

Co-authored-by: felix.boeckelmann <[email protected]>
Co-authored-by: Carlos Cordoba <[email protected]>
  • Loading branch information
3 people authored May 13, 2020
1 parent 462893c commit 6a7eae7
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 9 deletions.
33 changes: 28 additions & 5 deletions pyls/python_ls.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,14 +361,37 @@ def m_workspace__did_change_configuration(self, settings=None):
for doc_uri in workspace.documents:
self.lint(doc_uri, is_saved=False)

def m_workspace__did_change_workspace_folders(self, added=None, removed=None, **_kwargs):
def m_workspace__did_change_workspace_folders(self, event=None, **_kwargs): # pylint: disable=too-many-locals
if event is None:
return
added = event.get('added', [])
removed = event.get('removed', [])

for removed_info in removed:
removed_uri = removed_info['uri']
self.workspaces.pop(removed_uri)
if 'uri' in removed_info:
removed_uri = removed_info['uri']
self.workspaces.pop(removed_uri, None)

for added_info in added:
added_uri = added_info['uri']
self.workspaces[added_uri] = Workspace(added_uri, self._endpoint, self.config)
if 'uri' in added_info:
added_uri = added_info['uri']
self.workspaces[added_uri] = Workspace(added_uri, self._endpoint, self.config)

root_workspace_removed = any(removed_info['uri'] == self.root_uri for removed_info in removed)
workspace_added = len(added) > 0 and 'uri' in added[0]
if root_workspace_removed and workspace_added:
added_uri = added[0]['uri']
self.root_uri = added_uri
self.workspace = self.workspaces[added_uri]
elif root_workspace_removed:
# NOTE: Removing the root workspace can only happen when the server
# is closed, thus the else condition of this if can never happen.
if self.workspaces:
log.debug('Root workspace deleted!')
available_workspaces = sorted(self.workspaces)
first_workspace = available_workspaces[0]
self.root_uri = first_workspace
self.workspace = self.workspaces[first_workspace]

# Migrate documents that are on the root workspace and have a better
# match now
Expand Down
86 changes: 82 additions & 4 deletions test/test_workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ def test_multiple_workspaces(tmpdir, pyls):

added_workspaces = [{'uri': path_as_uri(str(x))}
for x in (workspace1_dir, workspace2_dir)]
pyls.m_workspace__did_change_workspace_folders(
added=added_workspaces, removed=[])
event = {'added': added_workspaces, 'removed': []}
pyls.m_workspace__did_change_workspace_folders(event)

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

pyls.m_workspace__did_change_workspace_folders(
added=[], removed=[added_workspaces[0]])
event = {'added': [], 'removed': [added_workspaces[0]]}
pyls.m_workspace__did_change_workspace_folders(event)
assert workspace1_uri not in pyls.workspaces


def test_multiple_workspaces_wrong_removed_uri(pyls):
workspace = {'uri': 'Test123'}
event = {'added': [], 'removed': [workspace]}
pyls.m_workspace__did_change_workspace_folders(event)
assert workspace['uri'] not in pyls.workspaces


def test_root_workspace_changed(pyls):
test_uri = 'Test123'
pyls.root_uri = test_uri
pyls.workspace._root_uri = test_uri

workspace1 = {'uri': test_uri}
workspace2 = {'uri': 'NewTest456'}

event = {'added': [workspace2], 'removed': [workspace1]}
pyls.m_workspace__did_change_workspace_folders(event)

assert workspace2['uri'] == pyls.workspace._root_uri
assert workspace2['uri'] == pyls.root_uri


def test_root_workspace_not_changed(pyls):
# removed uri != root_uri
test_uri_1 = 'Test12'
pyls.root_uri = test_uri_1
pyls.workspace._root_uri = test_uri_1
workspace1 = {'uri': 'Test1234'}
workspace2 = {'uri': 'NewTest456'}
event = {'added': [workspace2], 'removed': [workspace1]}
pyls.m_workspace__did_change_workspace_folders(event)
assert test_uri_1 == pyls.workspace._root_uri
assert test_uri_1 == pyls.root_uri
# empty 'added' list
test_uri_2 = 'Test123'
new_root_uri = workspace2['uri']
pyls.root_uri = test_uri_2
pyls.workspace._root_uri = test_uri_2
workspace1 = {'uri': test_uri_2}
event = {'added': [], 'removed': [workspace1]}
pyls.m_workspace__did_change_workspace_folders(event)
assert new_root_uri == pyls.workspace._root_uri
assert new_root_uri == pyls.root_uri
# empty 'removed' list
event = {'added': [workspace1], 'removed': []}
pyls.m_workspace__did_change_workspace_folders(event)
assert new_root_uri == pyls.workspace._root_uri
assert new_root_uri == pyls.root_uri
# 'added' list has no 'uri'
workspace2 = {'TESTuri': 'Test1234'}
event = {'added': [workspace2], 'removed': [workspace1]}
pyls.m_workspace__did_change_workspace_folders(event)
assert new_root_uri == pyls.workspace._root_uri
assert new_root_uri == pyls.root_uri


def test_root_workspace_removed(tmpdir, pyls):
workspace1_dir = tmpdir.mkdir('workspace1')
workspace2_dir = tmpdir.mkdir('workspace2')
root_uri = pyls.root_uri

# Add workspaces to the pyls
added_workspaces = [{'uri': path_as_uri(str(x))}
for x in (workspace1_dir, workspace2_dir)]
event = {'added': added_workspaces, 'removed': []}
pyls.m_workspace__did_change_workspace_folders(event)

# Remove the root workspace
removed_workspaces = [{'uri': root_uri}]
event = {'added': [], 'removed': removed_workspaces}
pyls.m_workspace__did_change_workspace_folders(event)

# Assert that the first of the workspaces (in alphabetical order) is now
# the root workspace
assert pyls.root_uri == path_as_uri(str(workspace1_dir))
assert pyls.workspace._root_uri == path_as_uri(str(workspace1_dir))

0 comments on commit 6a7eae7

Please sign in to comment.