From 46059ef736013a0900d70de9e94a329df8c069fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9B=BE=E6=A5=9A=E7=AC=91?= Date: Wed, 23 Sep 2026 05:26:37 +0800 Subject: [PATCH] Skip pathless definitions when collecting document symbols --- pylsp/plugins/symbols.py | 6 +++++- test/plugins/test_symbols.py | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/pylsp/plugins/symbols.py b/pylsp/plugins/symbols.py index 3a7beb07..1bf6b938 100644 --- a/pylsp/plugins/symbols.py +++ b/pylsp/plugins/symbols.py @@ -90,7 +90,11 @@ def pylsp_document_symbols(config, document): else: continue - if _include_def(d) and Path(document.path) == Path(d.module_path): + if ( + _include_def(d) + and d.module_path is not None + and Path(document.path) == Path(d.module_path) + ): tuple_range = _tuple_range(d) if tuple_range in exclude: continue diff --git a/test/plugins/test_symbols.py b/test/plugins/test_symbols.py index 242a38a1..a9c0874f 100644 --- a/test/plugins/test_symbols.py +++ b/test/plugins/test_symbols.py @@ -118,6 +118,44 @@ def test_symbols_non_existing_file(config, workspace, tmpdir) -> None: helper_check_symbols_all_scope(symbols) +@pytest.mark.parametrize("all_scopes", [False, True]) +@pytest.mark.parametrize("include_import_symbols", [False, True]) +def test_symbols_imported_namedtuple( + config, temp_workspace_factory, all_scopes, include_import_symbols +) -> None: + workspace = temp_workspace_factory( + { + "__init__.py": "", + "a.py": 'from .b import MyNamedTuple\na_symbol = "a_symbol"\n', + "b.py": ( + "from collections import namedtuple\n" + 'MyNamedTuple = namedtuple("MyNamedTuple", ["abc"])\n' + ), + } + ) + doc = workspace.get_document( + uris.from_fs_path(os.path.join(workspace.root_path, "a.py")) + ) + config.update( + { + "plugins": { + "jedi_symbols": { + "all_scopes": all_scopes, + "include_import_symbols": include_import_symbols, + } + } + } + ) + + symbols = pylsp_document_symbols(config, doc) + + expected = {"a_symbol": SymbolKind.Variable} + if include_import_symbols: + expected["MyNamedTuple"] = SymbolKind.Class + assert {symbol["name"]: symbol["kind"] for symbol in symbols} == expected + assert all(symbol["location"]["uri"] == doc.uri for symbol in symbols) + + @pytest.mark.skipif( PY2 or not LINUX or not CI, reason="tested on linux and python 3 only" )