Repository: python-lsp/python-lsp-server
Pull request #62 (2021-07-28 17:56:59)

Make use_document_path equal to True when getting definitions and hovers
This allows those plugins to work for files outside of the current workspace.


Patch:
diff --git a/pylsp/plugins/definition.py b/pylsp/plugins/definition.py
index c46b27a..98265fd 100644
--- a/pylsp/plugins/definition.py
+++ b/pylsp/plugins/definition.py
@@ -11,7 +11,7 @@ log = logging.getLogger(__name__)
 def pylsp_definitions(config, document, position):
     settings = config.plugin_settings('jedi_definition')
     code_position = _utils.position_to_jedi_linecolumn(document, position)
-    definitions = document.jedi_script().goto(
+    definitions = document.jedi_script(use_document_path=True).goto(
         follow_imports=settings.get('follow_imports', True),
         follow_builtin_imports=settings.get('follow_builtin_imports', True),
         **code_position)
diff --git a/pylsp/plugins/hover.py b/pylsp/plugins/hover.py
index e3e6fed..a4d45d1 100644
--- a/pylsp/plugins/hover.py
+++ b/pylsp/plugins/hover.py
@@ -11,7 +11,7 @@ log = logging.getLogger(__name__)
 @hookimpl
 def pylsp_hover(document, position):
     code_position = _utils.position_to_jedi_linecolumn(document, position)
-    definitions = document.jedi_script().infer(**code_position)
+    definitions = document.jedi_script(use_document_path=True).infer(**code_position)
     word = document.word_at_position(position)
 
     # Find first exact matching definition


Test patch:
diff --git a/test/plugins/test_definitions.py b/test/plugins/test_definitions.py
index f24b6c7..488f545 100644
--- a/test/plugins/test_definitions.py
+++ b/test/plugins/test_definitions.py
@@ -1,6 +1,8 @@
 # Copyright 2017-2020 Palantir Technologies, Inc.
 # Copyright 2021- Python Language Server Contributors.
 
+import os
+
 from pylsp import uris
 from pylsp.plugins.definition import pylsp_definitions
 from pylsp.workspace import Document
@@ -57,3 +59,36 @@ def test_assignment(config, workspace):
 
     doc = Document(DOC_URI, workspace, DOC)
     assert [{'uri': DOC_URI, 'range': def_range}] == pylsp_definitions(config, doc, cursor_pos)
+
+
+def test_document_path_definitions(config, workspace_other_root_path, tmpdir):
+    # Create a dummy module out of the workspace's root_path and try to get
+    # a definition on it in another file placed next to it.
+    module_content = '''
+def foo():
+    pass
+'''
+
+    p = tmpdir.join("mymodule.py")
+    p.write(module_content)
+
+    # Content of doc to test definition
+    doc_content = """from mymodule import foo"""
+    doc_path = str(tmpdir) + os.path.sep + 'myfile.py'
+    doc_uri = uris.from_fs_path(doc_path)
+    doc = Document(doc_uri, workspace_other_root_path, doc_content)
+
+    # The range where is defined in mymodule.py
+    def_range = {
+        'start': {'line': 1, 'character': 4},
+        'end': {'line': 1, 'character': 7}
+    }
+
+    # The position where foo is called in myfile.py
+    cursor_pos = {'line': 0, 'character': 24}
+
+    # The uri for mymodule.py
+    module_path = str(p)
+    module_uri = uris.from_fs_path(module_path)
+
+    assert [{'uri': module_uri, 'range': def_range}] == pylsp_definitions(config, doc, cursor_pos)
diff --git a/test/plugins/test_hover.py b/test/plugins/test_hover.py
index b78cbe8..7ac6e07 100644
--- a/test/plugins/test_hover.py
+++ b/test/plugins/test_hover.py
@@ -1,6 +1,8 @@
 # Copyright 2017-2020 Palantir Technologies, Inc.
 # Copyright 2021- Python Language Server Contributors.
 
+import os
+
 from pylsp import uris
 from pylsp.plugins.hover import pylsp_hover
 from pylsp.workspace import Document
@@ -72,3 +74,28 @@ def test_hover(workspace):
     } == pylsp_hover(doc, hov_position)
 
     assert {'contents': ''} == pylsp_hover(doc, no_hov_position)
+
+
+def test_document_path_hover(workspace_other_root_path, tmpdir):
+    # Create a dummy module out of the workspace's root_path and try to get
+    # a definition on it in another file placed next to it.
+    module_content = '''
+def foo():
+    """A docstring for foo."""
+    pass
+'''
+
+    p = tmpdir.join("mymodule.py")
+    p.write(module_content)
+
+    # Content of doc to test definition
+    doc_content = """from mymodule import foo
+foo"""
+    doc_path = str(tmpdir) + os.path.sep + 'myfile.py'
+    doc_uri = uris.from_fs_path(doc_path)
+    doc = Document(doc_uri, workspace_other_root_path, doc_content)
+
+    cursor_pos = {'line': 1, 'character': 3}
+    contents = pylsp_hover(doc, cursor_pos)['contents']
+
+    assert contents[1] == 'A docstring for foo.'
diff --git a/test/test_language_server.py b/test/test_language_server.py
index e39bf0a..0b5c1ae 100644
--- a/test/test_language_server.py
+++ b/test/test_language_server.py
@@ -75,6 +75,7 @@ def client_exited_server():
     assert client_server_pair.process.is_alive() is False
 
 
+@pytest.mark.skipif(sys.platform == 'darwin', reason='Too flaky on Mac')
 def test_initialize(client_server):  # pylint: disable=redefined-outer-name
     response = client_server._endpoint.request('initialize', {
         'rootPath': os.path.dirname(__file__),