Introduce abstraction DocumentSymbols, which is now returned by request_document_symbols

This commit is contained in:
Dominik Jain authored and Dominik Jain committed 2025-11-12 03:46:18 +01:00
1 parent 24ea449abf
commit d8cac3aedb
43 files changed
+198 -165

No files matched your search

+2 -1
View File
@@ -538,7 +538,8 @@ class ProjectCommands(AutoRegisteringGroup):
try:
for ls in ls_mgr.iter_language_servers():
click.echo(f"Indexing for language {ls.language.value} …")
symbols, _ = ls.request_document_symbols(file, include_body=False)
document_symbols = ls.request_document_symbols(file, include_body=False)
symbols, _ = document_symbols.get_all_symbols_and_roots()
ls.request_document_symbols(file, include_body=True)
if verbose:
click.echo(f"Symbols in file '{file}':")
+2 -8
View File
@@ -513,18 +513,12 @@ class LanguageServerSymbolRetriever:
)
return symbols
def get_document_symbols(self, relative_path: str) -> list[LanguageServerSymbol]:
lang_server = self.get_language_server(relative_path)
symbol_dicts, _roots = lang_server.request_document_symbols(relative_path, include_body=False)
symbols = [LanguageServerSymbol(s) for s in symbol_dicts]
return symbols
def find_by_location(self, location: LanguageServerSymbolLocation) -> LanguageServerSymbol | None:
if location.relative_path is None:
return None
lang_server = self.get_language_server(location.relative_path)
symbol_dicts, _roots = lang_server.request_document_symbols(location.relative_path, include_body=False)
for symbol_dict in symbol_dicts:
document_symbols = lang_server.request_document_symbols(location.relative_path, include_body=False)
for symbol_dict in document_symbols.iter_symbols():
symbol = LanguageServerSymbol(symbol_dict)
if symbol.location == location:
return symbol
@@ -713,7 +713,7 @@ class ALLanguageServer(SolidLanguageServer):
if os.path.isfile(within_abs_path):
# Single file case - use parent class implementation
_, root_nodes = self.request_document_symbols(within_relative_path, include_body=include_body)
root_nodes = self.request_document_symbols(within_relative_path, include_body=include_body).root_symbols
return root_nodes
# Directory case - scan within this directory
@@ -755,7 +755,7 @@ class ALLanguageServer(SolidLanguageServer):
try:
# Use our overridden request_document_symbols which handles opening
self.logger.log(f"AL: Getting symbols for {relative_path}", logging.DEBUG)
all_syms, root_syms = self.request_document_symbols(relative_path, include_body=include_body)
all_syms, root_syms = self.request_document_symbols(relative_path, include_body=include_body).get_all_symbols_and_roots()
if root_syms:
# Create a file-level symbol containing the document symbols
@@ -9,9 +9,8 @@ import pathlib
import shutil
import threading
from solidlsp import ls_types
from solidlsp.language_servers.common import RuntimeDependency, RuntimeDependencyCollection
from solidlsp.ls import SolidLanguageServer
from solidlsp.ls import DocumentSymbols, SolidLanguageServer
from solidlsp.ls_config import LanguageServerConfig
from solidlsp.ls_logger import LanguageServerLogger
from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams
@@ -194,9 +193,7 @@ class BashLanguageServer(SolidLanguageServer):
else:
self.logger.log("Bash server initialization complete", logging.INFO)
def request_document_symbols(
self, relative_file_path: str, include_body: bool = False
) -> tuple[list[ls_types.UnifiedSymbolInformation], list[ls_types.UnifiedSymbolInformation]]:
def request_document_symbols(self, relative_file_path: str, include_body: bool = False) -> DocumentSymbols:
"""
Request document symbols from bash-language-server via LSP.
@@ -212,19 +209,19 @@ class BashLanguageServer(SolidLanguageServer):
include_body: Whether to include function bodies in symbol information
Returns:
Tuple of (all_symbols, root_symbols) detected by the LSP server
The symbols
"""
self.logger.log(f"Requesting document symbols via LSP for {relative_file_path}", logging.DEBUG)
# Use the standard LSP approach - bash-language-server handles all function syntaxes correctly
all_symbols, root_symbols = super().request_document_symbols(relative_file_path, include_body)
document_symbols = super().request_document_symbols(relative_file_path, include_body)
# Log detection results for debugging
functions = [s for s in all_symbols if s.get("kind") == 12]
functions = [s for s in document_symbols.iter_symbols() if s.get("kind") == 12]
self.logger.log(
f"LSP function detection for {relative_file_path}: Found {len(functions)} functions",
logging.INFO,
)
return all_symbols, root_symbols
return document_symbols
@@ -12,7 +12,7 @@ import threading
from overrides import override
from solidlsp import ls_types
from solidlsp.ls import SolidLanguageServer
from solidlsp.ls import DocumentSymbols, SolidLanguageServer
from solidlsp.ls_config import LanguageServerConfig
from solidlsp.ls_logger import LanguageServerLogger
from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams
@@ -138,9 +138,7 @@ class FortranLanguageServer(SolidLanguageServer):
return symbol
@override
def request_document_symbols(
self, relative_file_path: str, include_body: bool = False
) -> tuple[list[ls_types.UnifiedSymbolInformation], list[ls_types.UnifiedSymbolInformation]]:
def request_document_symbols(self, relative_file_path: str, include_body: bool = False) -> DocumentSymbols:
"""
Override to fix fortls's incorrect selectionRange bug.
@@ -155,7 +153,7 @@ class FortranLanguageServer(SolidLanguageServer):
"""
# Get symbols from fortls (with incorrect selectionRange)
all_symbols, root_symbols = super().request_document_symbols(relative_file_path, include_body)
document_symbols = super().request_document_symbols(relative_file_path, include_body)
# Get file content for parsing
with self.open_file(relative_file_path) as file_data:
@@ -173,10 +171,9 @@ class FortranLanguageServer(SolidLanguageServer):
return fixed
# Apply fix to all symbols
fixed_all_symbols = [fix_symbol_and_children(sym) for sym in all_symbols]
fixed_root_symbols = [fix_symbol_and_children(sym) for sym in root_symbols]
fixed_root_symbols = [fix_symbol_and_children(sym) for sym in document_symbols.root_symbols]
return fixed_all_symbols, fixed_root_symbols
return DocumentSymbols(fixed_root_symbols)
@staticmethod
def _check_fortls_installation():
+5 -8
View File
@@ -16,7 +16,7 @@ from pathlib import Path
from overrides import override
from solidlsp import ls_types
from solidlsp.ls import SolidLanguageServer
from solidlsp.ls import DocumentSymbols, SolidLanguageServer
from solidlsp.ls_config import LanguageServerConfig
from solidlsp.ls_logger import LanguageServerLogger
from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams
@@ -70,9 +70,7 @@ class NixLanguageServer(SolidLanguageServer):
return symbol
@override
def request_document_symbols(
self, relative_file_path: str, include_body: bool = False
) -> tuple[list[ls_types.UnifiedSymbolInformation], list[ls_types.UnifiedSymbolInformation]]:
def request_document_symbols(self, relative_file_path: str, include_body: bool = False) -> DocumentSymbols:
"""
Override to extend Nix symbol ranges to include trailing semicolons.
@@ -80,7 +78,7 @@ class NixLanguageServer(SolidLanguageServer):
statement-level ranges (including semicolons) for proper symbol replacement.
"""
# Get symbols from parent implementation
all_symbols, root_symbols = super().request_document_symbols(relative_file_path, include_body)
document_symbols = super().request_document_symbols(relative_file_path, include_body)
# Get file content for range extension
file_content = self.language_server.retrieve_full_file_content(relative_file_path)
@@ -97,10 +95,9 @@ class NixLanguageServer(SolidLanguageServer):
return extended
# Apply range extension to all symbols
extended_all_symbols = [extend_symbol_and_children(sym) for sym in all_symbols]
extended_root_symbols = [extend_symbol_and_children(sym) for sym in root_symbols]
extended_root_symbols = [extend_symbol_and_children(sym) for sym in document_symbols.root_symbols]
return extended_all_symbols, extended_root_symbols
return DocumentSymbols(extended_root_symbols)
@override
def is_ignored_dirname(self, dirname: str) -> bool:
+56 -19
View File
@@ -17,7 +17,7 @@ from time import sleep
from typing import Self, Union, cast
import pathspec
from sensai.util.pickle import load_pickle
from sensai.util.pickle import getstate, load_pickle
from serena.text_utils import MatchedConsecutiveLines
from serena.util.file_system import match_path
@@ -80,6 +80,46 @@ class LSPFileBuffer:
self.content_hash = hashlib.md5(self.contents.encode("utf-8")).hexdigest()
class DocumentSymbols:
# IMPORTANT: Instances of this class are persisted in the high-level document symbol cache
def __init__(self, root_symbols: list[ls_types.UnifiedSymbolInformation]):
self.root_symbols = root_symbols
self._all_symbols: list[ls_types.UnifiedSymbolInformation] | None = None
def __getstate__(self):
return getstate(DocumentSymbols, self, transient_properties=["_all_symbols"])
def iter_symbols(self) -> Iterator[ls_types.UnifiedSymbolInformation]:
"""
Iterate over all symbols in the document symbol tree.
Yields symbols in a depth-first manner.
"""
if self._all_symbols is not None:
yield from self._all_symbols
return
def traverse(s: ls_types.UnifiedSymbolInformation):
yield s
for child in s.get("children", []):
yield from traverse(child)
for root_symbol in self.root_symbols:
yield from traverse(root_symbol)
def get_all_symbols_and_roots(self) -> tuple[list[ls_types.UnifiedSymbolInformation], list[ls_types.UnifiedSymbolInformation]]:
"""
This function returns all symbols in the document as a flat list and the root symbols.
It exists to facilitate migration from previous versions, where this was the return interface of
the LS method that obtained document symbols.
:return: A tuple containing a list of all symbols in the document and a list of root symbols.
"""
if self._all_symbols is None:
self._all_symbols = list(self.iter_symbols())
return self._all_symbols, self.root_symbols
class SolidLanguageServer(ABC):
"""
The LanguageServer class provides a language agnostic interface to the Language Server Protocol.
@@ -891,16 +931,14 @@ class SolidLanguageServer(ABC):
with self.open_file(relative_file_path) as opened_file_data:
return get_symbols(opened_file_data)
def request_document_symbols(
self, relative_file_path: str, include_body: bool = False
) -> tuple[list[ls_types.UnifiedSymbolInformation], list[ls_types.UnifiedSymbolInformation]]:
def request_document_symbols(self, relative_file_path: str, include_body: bool = False) -> DocumentSymbols:
"""
Retrieves the full list of symbols in the given file, along with the root symbols that represent the tree structure of the symbols.
Retrieves the collection of symbols in the given file
:param relative_file_path: The relative path of the file that has the symbols
:param include_body: whether to include the body of the symbols in the result.
:return: A list of symbols in the file, and a list of root symbols that represent the tree structure of the symbols.
All symbols will have a location, children, and a parent attribute,
:return: the collection of symbols in the file.
All contained symbols will have a location, children, and a parent attribute,
where the parent attribute is None for root symbols.
Note that this is slightly different from the call to request_full_symbol_tree,
where the parent attribute will be the file symbol which in turn may have a package symbol as parent.
@@ -1004,8 +1042,7 @@ class SolidLanguageServer(ABC):
root_nodes: list[ls_types.UnifiedSymbolInformation] = response
convert_nodes_with_common_parent(root_nodes, None)
result = flat_all_symbol_list, root_nodes
result = DocumentSymbols(root_nodes)
# update cache
"""
@@ -1050,7 +1087,7 @@ class SolidLanguageServer(ABC):
)
return []
else:
_, root_nodes = self.request_document_symbols(within_relative_path, include_body=include_body)
root_nodes = self.request_document_symbols(within_relative_path, include_body=include_body).root_symbols
return root_nodes
# Helper function to recursively process directories
@@ -1109,7 +1146,8 @@ class SolidLanguageServer(ABC):
child["parent"] = package_symbol
elif os.path.isfile(contained_dir_or_file_abs_path):
_, file_root_nodes = self.request_document_symbols(contained_dir_or_file_rel_path, include_body=include_body)
document_symbols = self.request_document_symbols(contained_dir_or_file_rel_path, include_body=include_body)
file_root_nodes = document_symbols.root_symbols
# Create file symbol, link with children
file_rel_path = str(Path(contained_dir_or_file_abs_path).resolve().relative_to(self.repository_root_path))
@@ -1218,8 +1256,7 @@ class SolidLanguageServer(ABC):
"""
:return: the top-level symbols in the given file.
"""
_, document_roots = self.request_document_symbols(relative_file_path)
return document_roots
return self.request_document_symbols(relative_file_path).root_symbols
def request_overview(self, within_relative_path: str) -> dict[str, list[UnifiedSymbolInformation]]:
"""
@@ -1356,8 +1393,8 @@ class SolidLanguageServer(ABC):
ref_text = file_data.contents.split("\n")[ref_line]
if "." in ref_text:
containing_symbol_name = ref_text.split(".")[0]
all_symbols, _ = self.request_document_symbols(ref_path)
for symbol in all_symbols:
document_symbols = self.request_document_symbols(ref_path)
for symbol in document_symbols.iter_symbols():
if symbol["name"] == containing_symbol_name and symbol["kind"] == ls_types.SymbolKind.Variable:
containing_symbol = copy(symbol)
containing_symbol["location"] = ref
@@ -1478,12 +1515,12 @@ class SolidLanguageServer(ABC):
)
return None
symbols, _ = self.request_document_symbols(relative_file_path)
document_symbols = self.request_document_symbols(relative_file_path)
# make jedi and pyright api compatible
# the former has no location, the later has no range
# we will just always add location of the desired format to all symbols
for symbol in symbols:
for symbol in document_symbols.iter_symbols():
if "location" not in symbol:
range = symbol["range"]
location = ls_types.Location(
@@ -1521,10 +1558,10 @@ class SolidLanguageServer(ABC):
# Only consider containers that are not one-liners (otherwise we may get imports)
candidate_containers = [
s
for s in symbols
for s in document_symbols.iter_symbols()
if s["kind"] in container_symbol_kinds and s["location"]["range"]["start"]["line"] != s["location"]["range"]["end"]["line"]
]
var_containers = [s for s in symbols if s["kind"] == ls_types.SymbolKind.Variable]
var_containers = [s for s in document_symbols.iter_symbols() if s["kind"] == ls_types.SymbolKind.Variable]
candidate_containers.extend(var_containers)
if not candidate_containers:
+3 -3
View File
@@ -43,7 +43,7 @@ class TestALLanguageServer:
def test_find_table_fields(self, language_server: SolidLanguageServer) -> None:
"""Test that AL Language Server can find fields within a table."""
file_path = os.path.join("src", "Tables", "Customer.Table.al")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# AL tables should have their fields as child symbols
customer_table = None
@@ -76,7 +76,7 @@ class TestALLanguageServer:
def test_find_procedures(self, language_server: SolidLanguageServer) -> None:
"""Test that AL Language Server can find procedures in codeunits."""
file_path = os.path.join("src", "Codeunits", "CustomerMgt.Codeunit.al")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Find the codeunit symbol - AL returns 'Codeunit 50000 CustomerMgt'
codeunit_symbol = None
@@ -100,7 +100,7 @@ class TestALLanguageServer:
"""Test that AL Language Server can find references to symbols."""
# Find references to the Customer table from the CustomerMgt codeunit
table_file = os.path.join("src", "Tables", "Customer.Table.al")
symbols = language_server.request_document_symbols(table_file)
symbols = language_server.request_document_symbols(table_file).get_all_symbols_and_roots()
# Find the Customer table symbol
customer_symbol = None
+11 -5
View File
@@ -25,7 +25,7 @@ class TestBashLanguageServerBasics:
def test_bash_request_document_symbols(self, language_server: SolidLanguageServer) -> None:
"""Test request_document_symbols for bash files."""
# Test getting symbols from main.sh
all_symbols, _root_symbols = language_server.request_document_symbols("main.sh", include_body=False)
all_symbols, _root_symbols = language_server.request_document_symbols("main.sh", include_body=False).get_all_symbols_and_roots()
# Extract function symbols (LSP Symbol Kind 12)
function_symbols = [symbol for symbol in all_symbols if symbol.get("kind") == 12]
@@ -41,7 +41,7 @@ class TestBashLanguageServerBasics:
def test_bash_request_document_symbols_with_body(self, language_server: SolidLanguageServer) -> None:
"""Test request_document_symbols with body extraction."""
# Test with include_body=True
all_symbols, _root_symbols = language_server.request_document_symbols("main.sh", include_body=True)
all_symbols, _root_symbols = language_server.request_document_symbols("main.sh", include_body=True).get_all_symbols_and_roots()
function_symbols = [symbol for symbol in all_symbols if symbol.get("kind") == 12]
@@ -58,7 +58,9 @@ class TestBashLanguageServerBasics:
def test_bash_utils_functions(self, language_server: SolidLanguageServer) -> None:
"""Test function detection in utils.sh file."""
# Test with utils.sh as well
utils_all_symbols, _utils_root_symbols = language_server.request_document_symbols("utils.sh", include_body=False)
utils_all_symbols, _utils_root_symbols = language_server.request_document_symbols(
"utils.sh", include_body=False
).get_all_symbols_and_roots()
utils_function_symbols = [symbol for symbol in utils_all_symbols if symbol.get("kind") == 12]
utils_function_names = [symbol["name"] for symbol in utils_function_symbols]
@@ -84,12 +86,16 @@ class TestBashLanguageServerBasics:
def test_bash_function_syntax_patterns(self, language_server: SolidLanguageServer) -> None:
"""Test that LSP detects different bash function syntax patterns correctly."""
# Test main.sh (has both 'function' keyword and traditional syntax)
main_all_symbols, _main_root_symbols = language_server.request_document_symbols("main.sh", include_body=False)
main_all_symbols, _main_root_symbols = language_server.request_document_symbols(
"main.sh", include_body=False
).get_all_symbols_and_roots()
main_functions = [symbol for symbol in main_all_symbols if symbol.get("kind") == 12]
main_function_names = [func["name"] for func in main_functions]
# Test utils.sh (all use 'function' keyword)
utils_all_symbols, _utils_root_symbols = language_server.request_document_symbols("utils.sh", include_body=False)
utils_all_symbols, _utils_root_symbols = language_server.request_document_symbols(
"utils.sh", include_body=False
).get_all_symbols_and_roots()
utils_functions = [symbol for symbol in utils_all_symbols if symbol.get("kind") == 12]
utils_function_names = [func["name"] for func in utils_functions]
+1 -1
View File
@@ -53,7 +53,7 @@ class TestLanguageServerBasics:
@pytest.mark.parametrize("language_server", [Language.CLOJURE], indirect=True)
def test_document_symbols(self, language_server: SolidLanguageServer):
symbols, _ = language_server.request_document_symbols(CORE_PATH)
symbols, _ = language_server.request_document_symbols(CORE_PATH).get_all_symbols_and_roots()
assert isinstance(symbols, list) and len(symbols) >= 4, "greet, add, multiply, -main functions"
+4 -4
View File
@@ -31,7 +31,7 @@ class TestCSharpLanguageServer:
def test_get_document_symbols(self, language_server: SolidLanguageServer) -> None:
"""Test getting document symbols from a C# file."""
file_path = os.path.join("Program.cs")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Check that we have symbols
assert len(symbols) > 0
@@ -49,7 +49,7 @@ class TestCSharpLanguageServer:
def test_find_referencing_symbols(self, language_server: SolidLanguageServer) -> None:
"""Test finding references using symbol selection range."""
file_path = os.path.join("Program.cs")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
add_symbol = None
# Handle nested symbol structure
symbol_list = symbols[0] if symbols and isinstance(symbols[0], list) else symbols
@@ -68,7 +68,7 @@ class TestCSharpLanguageServer:
def test_nested_namespace_symbols(self, language_server: SolidLanguageServer) -> None:
"""Test getting symbols from nested namespace."""
file_path = os.path.join("Models", "Person.cs")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Check that we have symbols
assert len(symbols) > 0
@@ -93,7 +93,7 @@ class TestCSharpLanguageServer:
"""Test finding references to Calculator.Subtract method across files."""
# First, find the Subtract method in Program.cs
file_path = os.path.join("Program.cs")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Flatten the symbols if they're nested
symbol_list = symbols[0] if symbols and isinstance(symbols[0], list) else symbols
+4 -4
View File
@@ -171,7 +171,7 @@ class TestDartLanguageServer:
def test_find_referencing_symbols(self, language_server: SolidLanguageServer) -> None:
"""Test finding references using symbol selection range."""
file_path = os.path.join("lib", "main.dart")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Handle nested symbol structure - symbols can be nested in lists
symbol_list = symbols[0] if symbols and isinstance(symbols[0], list) else symbols
@@ -281,7 +281,7 @@ class TestDartLanguageServer:
def test_request_document_symbols(self, language_server: SolidLanguageServer) -> None:
"""Test getting document symbols from a Dart file."""
file_path = os.path.join("lib", "main.dart")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Check that we have symbols
assert len(symbols) > 0
@@ -308,7 +308,7 @@ class TestDartLanguageServer:
def test_request_referencing_symbols_comprehensive(self, language_server: SolidLanguageServer) -> None:
"""Test comprehensive referencing symbols functionality."""
file_path = os.path.join("lib", "main.dart")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Handle nested symbol structure
symbol_list = symbols[0] if symbols and isinstance(symbols[0], list) else symbols
@@ -339,7 +339,7 @@ class TestDartLanguageServer:
helper_file_path = os.path.join("lib", "helper.dart")
# Test finding references to subtract function from helper.dart in main.dart
helper_symbols = language_server.request_document_symbols(helper_file_path)
helper_symbols = language_server.request_document_symbols(helper_file_path).get_all_symbols_and_roots()
symbol_list = helper_symbols[0] if helper_symbols and isinstance(helper_symbols[0], list) else helper_symbols
subtract_symbol = next((s for s in symbol_list if s.get("name") == "subtract"), None)
+5 -5
View File
@@ -25,7 +25,7 @@ class TestElixirBasic:
def test_request_references_function_definition(self, language_server: SolidLanguageServer):
"""Test finding references to a function definition."""
file_path = os.path.join("lib", "models.ex")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Find the User module's 'new' function
user_new_symbol = None
@@ -54,7 +54,7 @@ class TestElixirBasic:
def test_request_references_create_user_function(self, language_server: SolidLanguageServer):
"""Test finding references to create_user function."""
file_path = os.path.join("lib", "services.ex")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Find the UserService module's 'create_user' function
create_user_symbol = None
@@ -79,7 +79,7 @@ class TestElixirBasic:
def test_request_referencing_symbols_function(self, language_server: SolidLanguageServer):
"""Test finding symbols that reference a specific function."""
file_path = os.path.join("lib", "models.ex")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Find the User module's 'new' function
user_new_symbol = None
@@ -103,10 +103,10 @@ class TestElixirBasic:
def test_timeout_enumeration_bug(self, language_server: SolidLanguageServer):
"""Test that enumeration doesn't timeout (regression test)."""
# This should complete without timing out
symbols = language_server.request_document_symbols("lib/models.ex")
symbols = language_server.request_document_symbols("lib/models.ex").get_all_symbols_and_roots()
assert symbols is not None
# Test multiple symbol requests in succession
for _ in range(3):
symbols = language_server.request_document_symbols("lib/services.ex")
symbols = language_server.request_document_symbols("lib/services.ex").get_all_symbols_and_roots()
assert symbols is not None
@@ -46,7 +46,7 @@ def test_find_references_ignores_dir(ls_with_ignored_dirs: SolidLanguageServer):
definition_file = "lib/models.ex"
# Find the User struct definition
symbols = ls_with_ignored_dirs.request_document_symbols(definition_file)
symbols = ls_with_ignored_dirs.request_document_symbols(definition_file).get_all_symbols_and_roots()
user_symbol = None
for symbol_group in symbols:
user_symbol = next((s for s in symbol_group if "User" in s.get("name", "")), None)
@@ -87,7 +87,7 @@ def test_refs_and_symbols_with_glob_patterns(repo_path: Path) -> None:
definition_file = "lib/models.ex"
# Find the User struct definition
symbols = ls.request_document_symbols(definition_file)
symbols = ls.request_document_symbols(definition_file).get_all_symbols_and_roots()
user_symbol = None
for symbol_group in symbols:
user_symbol = next((s for s in symbol_group if "User" in s.get("name", "")), None)
@@ -72,7 +72,7 @@ class TestElixirIntegration:
def test_module_hierarchy_understanding(self, language_server: SolidLanguageServer):
"""Test that the language server understands Elixir module hierarchy."""
models_file = os.path.join("lib", "models.ex")
symbols = language_server.request_document_symbols(models_file)
symbols = language_server.request_document_symbols(models_file).get_all_symbols_and_roots()
if symbols:
# Flatten symbol structure
@@ -120,7 +120,7 @@ class TestElixirLanguageServerSymbols:
# Test referencing symbols for User struct
file_path = os.path.join("lib", "models.ex")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
user_symbol = None
for symbol_group in symbols:
user_symbol = next((s for s in symbol_group if "User" in s.get("name", "")), None)
+2 -2
View File
@@ -20,7 +20,7 @@ class TestElmLanguageServer:
@pytest.mark.parametrize("language_server", [Language.ELM], indirect=True)
def test_find_references_within_file(self, language_server: SolidLanguageServer) -> None:
file_path = os.path.join("Main.elm")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
greet_symbol = None
for sym in symbols[0]:
if sym.get("name") == "greet":
@@ -35,7 +35,7 @@ class TestElmLanguageServer:
def test_find_references_across_files(self, language_server: SolidLanguageServer) -> None:
# Test formatMessage function which is defined in Utils.elm and used in Main.elm
utils_path = os.path.join("Utils.elm")
symbols = language_server.request_document_symbols(utils_path)
symbols = language_server.request_document_symbols(utils_path).get_all_symbols_and_roots()
formatMessage_symbol = None
for sym in symbols[0]:
if sym.get("name") == "formatMessage":
+1 -1
View File
@@ -29,7 +29,7 @@ class TestErlangLanguageServerBasics:
"""Test document symbols retrieval for Erlang files."""
try:
file_path = "hello.erl"
symbols_tuple = language_server.request_document_symbols(file_path)
symbols_tuple = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
assert isinstance(symbols_tuple, tuple)
assert len(symbols_tuple) == 2
@@ -63,7 +63,7 @@ def test_find_references_ignores_dir(ls_with_ignored_dirs: SolidLanguageServer):
definition_file = "include/records.hrl"
# Find the user record definition
symbols = ls_with_ignored_dirs.request_document_symbols(definition_file)
symbols = ls_with_ignored_dirs.request_document_symbols(definition_file).get_all_symbols_and_roots()
user_symbol = None
for symbol_group in symbols:
user_symbol = next((s for s in symbol_group if "user" in s.get("name", "").lower()), None)
@@ -107,7 +107,7 @@ def test_refs_and_symbols_with_glob_patterns(repo_path: Path) -> None:
definition_file = "include/records.hrl"
# Find the user record definition
symbols = ls.request_document_symbols(definition_file)
symbols = ls.request_document_symbols(definition_file).get_all_symbols_and_roots()
user_symbol = None
for symbol_group in symbols:
user_symbol = next((s for s in symbol_group if "user" in s.get("name", "").lower()), None)
@@ -203,7 +203,7 @@ def test_document_symbols_ignores_dirs(ls_with_ignored_dirs: SolidLanguageServer
# Try to get symbols from a file in ignored directory (should not find it)
try:
ignored_file = "ignored_dir/ignored_module.erl"
symbols = ls_with_ignored_dirs.request_document_symbols(ignored_file)
symbols = ls_with_ignored_dirs.request_document_symbols(ignored_file).get_all_symbols_and_roots()
# If we get here, the file was found - symbols should be empty or None
if symbols:
assert len(symbols) == 0, "Should not find symbols in ignored directory"
@@ -126,7 +126,7 @@ class TestErlangLanguageServerSymbols:
# Test referencing symbols for user record
file_path = os.path.join("include", "records.hrl")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
user_symbol = None
for symbol_group in symbols:
user_symbol = next((s for s in symbol_group if "user" in s.get("name", "")), None)
@@ -156,7 +156,7 @@ class TestErlangLanguageServerSymbols:
# Test referencing symbols for create_user function
file_path = os.path.join("src", "models.erl")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
create_user_symbol = None
for symbol_group in symbols:
create_user_symbol = next((s for s in symbol_group if "create_user" in s.get("name", "")), None)
@@ -418,7 +418,7 @@ class TestErlangLanguageServerSymbols:
# Test that we can find references to models module functions in services.erl
file_path = os.path.join("src", "models.erl")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
create_user_symbol = None
for symbol_group in symbols:
create_user_symbol = next((s for s in symbol_group if "create_user" in s.get("name", "")), None)
+5 -5
View File
@@ -41,12 +41,12 @@ class TestFortranLanguageServer:
def test_request_document_symbols(self, language_server: SolidLanguageServer) -> None:
"""Test that document symbols can be retrieved from Fortran files."""
# Test main.f90 - should have a program symbol
main_symbols, _ = language_server.request_document_symbols("main.f90")
main_symbols, _ = language_server.request_document_symbols("main.f90").get_all_symbols_and_roots()
program_names = [s.get("name") for s in main_symbols]
assert "test_program" in program_names, f"Program 'test_program' not found in main.f90. Found: {program_names}"
# Test modules/math_utils.f90 - should have module and function symbols
module_symbols, _ = language_server.request_document_symbols("modules/math_utils.f90")
module_symbols, _ = language_server.request_document_symbols("modules/math_utils.f90").get_all_symbols_and_roots()
all_names = [s.get("name") for s in module_symbols]
assert "math_utils" in all_names, f"Module 'math_utils' not found. Found: {all_names}"
assert "add_numbers" in all_names, f"Function 'add_numbers' not found. Found: {all_names}"
@@ -60,7 +60,7 @@ class TestFortranLanguageServer:
This tests the LSP textDocument/references capability.
"""
file_path = "modules/math_utils.f90"
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Find the add_numbers function
add_numbers_symbol = None
@@ -125,7 +125,7 @@ class TestFortranLanguageServer:
"""
# Get the add_numbers function symbol from math_utils.f90
file_path = "modules/math_utils.f90"
symbols, _ = language_server.request_document_symbols(file_path)
symbols, _ = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Find the add_numbers function
add_numbers_symbol = None
@@ -230,7 +230,7 @@ class TestFortranLanguageServer:
fortls returns these as SymbolKind.Class (11) for types and SymbolKind.Interface (5) for interfaces.
"""
file_path = "modules/geometry.f90"
symbols, _ = language_server.request_document_symbols(file_path)
symbols, _ = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Find type and interface symbols
type_names = []
+1 -1
View File
@@ -19,7 +19,7 @@ class TestGoLanguageServer:
@pytest.mark.parametrize("language_server", [Language.GO], indirect=True)
def test_find_referencing_symbols(self, language_server: SolidLanguageServer) -> None:
file_path = os.path.join("main.go")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
helper_symbol = None
for sym in symbols[0]:
if sym.get("name") == "Helper":
+3 -3
View File
@@ -34,7 +34,7 @@ class TestHaskellLanguageServer:
- All exported functions with correct names
- Module structure
"""
all_symbols, _ = language_server.request_document_symbols("src/Calculator.hs")
all_symbols, _ = language_server.request_document_symbols("src/Calculator.hs").get_all_symbols_and_roots()
symbol_names = {s["name"] for s in all_symbols}
# Verify exact set of expected top-level symbols
@@ -71,7 +71,7 @@ class TestHaskellLanguageServer:
Verifies Serena identifies all helper functions that are imported
and used by Calculator module.
"""
all_symbols, _ = language_server.request_document_symbols("src/Helper.hs")
all_symbols, _ = language_server.request_document_symbols("src/Helper.hs").get_all_symbols_and_roots()
symbol_names = {s["name"] for s in all_symbols}
# Verify expected helper functions (module name may also appear)
@@ -97,7 +97,7 @@ class TestHaskellLanguageServer:
Verifies Serena can identify cross-module dependencies.
"""
all_symbols, _ = language_server.request_document_symbols("app/Main.hs")
all_symbols, _ = language_server.request_document_symbols("app/Main.hs").get_all_symbols_and_roots()
symbol_names = {s["name"] for s in all_symbols}
# Main.hs should have the main function
+1 -1
View File
@@ -25,7 +25,7 @@ class TestJavaLanguageServer:
# Dynamically determine the correct line/column for the 'Model' class name
file_path = os.path.join("src", "main", "java", "test_repo", "Model.java")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
model_symbol = None
for sym in symbols[0]:
if sym.get("name") == "Model" and sym.get("kind") == 5: # 5 = Class
+1 -1
View File
@@ -11,7 +11,7 @@ class TestJuliaLanguageServer:
"""
Test if we can find the top-level symbols in the main.jl file.
"""
all_symbols, _ = language_server.request_document_symbols("main.jl")
all_symbols, _ = language_server.request_document_symbols("main.jl").get_all_symbols_and_roots()
symbol_names = {s["name"] for s in all_symbols}
assert "calculate_sum" in symbol_names
assert "main" in symbol_names
+1 -1
View File
@@ -25,7 +25,7 @@ class TestKotlinLanguageServer:
# Dynamically determine the correct line/column for the 'Model' class name
file_path = os.path.join("src", "main", "kotlin", "test_repo", "Model.kt")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
model_symbol = None
for sym in symbols[0]:
print(sym)
+6 -6
View File
@@ -19,7 +19,7 @@ class TestLuaLanguageServer:
@pytest.mark.parametrize("language_server", [Language.LUA], indirect=True)
def test_find_symbols_in_calculator(self, language_server: SolidLanguageServer) -> None:
"""Test finding specific functions in calculator.lua."""
symbols = language_server.request_document_symbols("src/calculator.lua")
symbols = language_server.request_document_symbols("src/calculator.lua").get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -49,7 +49,7 @@ class TestLuaLanguageServer:
@pytest.mark.parametrize("language_server", [Language.LUA], indirect=True)
def test_find_symbols_in_utils(self, language_server: SolidLanguageServer) -> None:
"""Test finding specific functions in utils.lua."""
symbols = language_server.request_document_symbols("src/utils.lua")
symbols = language_server.request_document_symbols("src/utils.lua").get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -84,7 +84,7 @@ class TestLuaLanguageServer:
@pytest.mark.parametrize("language_server", [Language.LUA], indirect=True)
def test_find_symbols_in_main(self, language_server: SolidLanguageServer) -> None:
"""Test finding functions in main.lua."""
symbols = language_server.request_document_symbols("main.lua")
symbols = language_server.request_document_symbols("main.lua").get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -107,7 +107,7 @@ class TestLuaLanguageServer:
@pytest.mark.parametrize("language_server", [Language.LUA], indirect=True)
def test_cross_file_references_calculator_add(self, language_server: SolidLanguageServer) -> None:
"""Test finding cross-file references to calculator.add function."""
symbols = language_server.request_document_symbols("src/calculator.lua")
symbols = language_server.request_document_symbols("src/calculator.lua").get_all_symbols_and_roots()
assert symbols is not None
symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
@@ -163,7 +163,7 @@ class TestLuaLanguageServer:
@pytest.mark.parametrize("language_server", [Language.LUA], indirect=True)
def test_cross_file_references_utils_trim(self, language_server: SolidLanguageServer) -> None:
"""Test finding cross-file references to utils.trim function."""
symbols = language_server.request_document_symbols("src/utils.lua")
symbols = language_server.request_document_symbols("src/utils.lua").get_all_symbols_and_roots()
assert symbols is not None
symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
@@ -245,7 +245,7 @@ class TestLuaLanguageServer:
def test_references_between_test_and_source(self, language_server: SolidLanguageServer) -> None:
"""Test finding references from test files to source files."""
# Check if test_calculator.lua references calculator module
test_symbols = language_server.request_document_symbols("tests/test_calculator.lua")
test_symbols = language_server.request_document_symbols("tests/test_calculator.lua").get_all_symbols_and_roots()
assert test_symbols is not None
assert len(test_symbols) > 0
@@ -25,7 +25,7 @@ class TestMarkdownLanguageServerBasics:
def test_markdown_request_document_symbols(self, language_server: SolidLanguageServer) -> None:
"""Test request_document_symbols for markdown files."""
# Test getting symbols from README.md
all_symbols, _root_symbols = language_server.request_document_symbols("README.md", include_body=False)
all_symbols, _root_symbols = language_server.request_document_symbols("README.md", include_body=False).get_all_symbols_and_roots()
# Extract heading symbols (LSP Symbol Kind 15 is String, but marksman uses kind 15 for headings)
# Note: Different markdown LSPs may use different symbol kinds for headings
@@ -38,7 +38,7 @@ class TestMarkdownLanguageServerBasics:
@pytest.mark.parametrize("language_server", [Language.MARKDOWN], indirect=True)
def test_markdown_request_symbols_from_guide(self, language_server: SolidLanguageServer) -> None:
"""Test symbol detection in guide.md file."""
all_symbols, _root_symbols = language_server.request_document_symbols("guide.md", include_body=False)
all_symbols, _root_symbols = language_server.request_document_symbols("guide.md", include_body=False).get_all_symbols_and_roots()
# At least some headings should be found
assert len(all_symbols) > 0, f"Should find headings in guide.md, found {len(all_symbols)}"
@@ -46,7 +46,7 @@ class TestMarkdownLanguageServerBasics:
@pytest.mark.parametrize("language_server", [Language.MARKDOWN], indirect=True)
def test_markdown_request_symbols_from_api(self, language_server: SolidLanguageServer) -> None:
"""Test symbol detection in api.md file."""
all_symbols, _root_symbols = language_server.request_document_symbols("api.md", include_body=False)
all_symbols, _root_symbols = language_server.request_document_symbols("api.md", include_body=False).get_all_symbols_and_roots()
# Should detect headings from api.md
assert len(all_symbols) > 0, f"Should find headings in api.md, found {len(all_symbols)}"
@@ -55,7 +55,7 @@ class TestMarkdownLanguageServerBasics:
def test_markdown_request_document_symbols_with_body(self, language_server: SolidLanguageServer) -> None:
"""Test request_document_symbols with body extraction."""
# Test with include_body=True
all_symbols, _root_symbols = language_server.request_document_symbols("README.md", include_body=True)
all_symbols, _root_symbols = language_server.request_document_symbols("README.md", include_body=True).get_all_symbols_and_roots()
# Should have found some symbols
assert len(all_symbols) > 0, "Should find symbols in README.md"
+7 -7
View File
@@ -22,7 +22,7 @@ class TestNixLanguageServer:
@pytest.mark.parametrize("language_server", [Language.NIX], indirect=True)
def test_find_symbols_in_default_nix(self, language_server: SolidLanguageServer) -> None:
"""Test finding specific symbols in default.nix."""
symbols = language_server.request_document_symbols("default.nix")
symbols = language_server.request_document_symbols("default.nix").get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -42,7 +42,7 @@ class TestNixLanguageServer:
@pytest.mark.parametrize("language_server", [Language.NIX], indirect=True)
def test_find_symbols_in_utils(self, language_server: SolidLanguageServer) -> None:
"""Test finding symbols in lib/utils.nix."""
symbols = language_server.request_document_symbols("lib/utils.nix")
symbols = language_server.request_document_symbols("lib/utils.nix").get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -58,7 +58,7 @@ class TestNixLanguageServer:
@pytest.mark.parametrize("language_server", [Language.NIX], indirect=True)
def test_find_symbols_in_flake(self, language_server: SolidLanguageServer) -> None:
"""Test finding symbols in flake.nix."""
symbols = language_server.request_document_symbols("flake.nix")
symbols = language_server.request_document_symbols("flake.nix").get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -72,7 +72,7 @@ class TestNixLanguageServer:
@pytest.mark.parametrize("language_server", [Language.NIX], indirect=True)
def test_find_symbols_in_module(self, language_server: SolidLanguageServer) -> None:
"""Test finding symbols in a NixOS module."""
symbols = language_server.request_document_symbols("modules/example.nix")
symbols = language_server.request_document_symbols("modules/example.nix").get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -86,7 +86,7 @@ class TestNixLanguageServer:
@pytest.mark.parametrize("language_server", [Language.NIX], indirect=True)
def test_find_references_within_file(self, language_server: SolidLanguageServer) -> None:
"""Test finding references within the same file."""
symbols = language_server.request_document_symbols("default.nix")
symbols = language_server.request_document_symbols("default.nix").get_all_symbols_and_roots()
assert symbols is not None
symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
@@ -154,7 +154,7 @@ class TestNixLanguageServer:
def test_verify_imports_exist(self, language_server: SolidLanguageServer) -> None:
"""Verify that our test files have proper imports set up."""
# Verify that default.nix imports utils from lib/utils.nix
symbols = language_server.request_document_symbols("default.nix")
symbols = language_server.request_document_symbols("default.nix").get_all_symbols_and_roots()
assert symbols is not None
symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
@@ -164,7 +164,7 @@ class TestNixLanguageServer:
assert "makeGreeting" in symbol_names, "makeGreeting should be found in default.nix"
# Verify lib/utils.nix has the expected structure
utils_symbols = language_server.request_document_symbols("lib/utils.nix")
utils_symbols = language_server.request_document_symbols("lib/utils.nix").get_all_symbols_and_roots()
assert utils_symbols is not None
utils_list = utils_symbols[0] if isinstance(utils_symbols, tuple) else utils_symbols
utils_names = {sym.get("name") for sym in utils_list if isinstance(sym, dict)}
+1 -1
View File
@@ -31,7 +31,7 @@ class TestPerlLanguageServer:
def test_document_symbols(self, language_server: SolidLanguageServer) -> None:
"""Test that document symbols are correctly identified."""
# Request document symbols
all_symbols, _ = language_server.request_document_symbols("main.pl", include_body=False)
all_symbols, _ = language_server.request_document_symbols("main.pl", include_body=False).get_all_symbols_and_roots()
assert all_symbols, "Expected to find symbols in main.pl"
assert len(all_symbols) > 0, "Expected at least one symbol"
+4 -4
View File
@@ -26,7 +26,7 @@ class TestLanguageServerBasics:
file_path = os.path.join("test_repo", "models.py")
# Line 31 contains the User class definition
# Use selectionRange only
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
user_symbol = next((s for s in symbols[0] if s.get("name") == "User"), None)
if not user_symbol or "selectionRange" not in user_symbol:
raise AssertionError("User symbol or its selectionRange not found")
@@ -41,7 +41,7 @@ class TestLanguageServerBasics:
file_path = os.path.join("test_repo", "models.py")
# Line 56 contains the Item class definition
# Use selectionRange only
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
item_symbol = next((s for s in symbols[0] if s.get("name") == "Item"), None)
if not item_symbol or "selectionRange" not in item_symbol:
raise AssertionError("Item symbol or its selectionRange not found")
@@ -57,7 +57,7 @@ class TestLanguageServerBasics:
file_path = os.path.join("test_repo", "services.py")
# Line 24 contains the get_user method with id parameter
# Use selectionRange only
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
get_user_symbol = next((s for s in symbols[0] if s.get("name") == "get_user"), None)
if not get_user_symbol or "selectionRange" not in get_user_symbol:
raise AssertionError("get_user symbol or its selectionRange not found")
@@ -71,7 +71,7 @@ class TestLanguageServerBasics:
file_path = os.path.join("test_repo", "services.py")
# Line 15 contains the create_user method definition
# Use selectionRange only
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
create_user_symbol = next((s for s in symbols[0] if s.get("name") == "create_user"), None)
if not create_user_symbol or "selectionRange" not in create_user_symbol:
raise AssertionError("create_user symbol or its selectionRange not found")
@@ -107,7 +107,7 @@ class TestLanguageServerSymbols:
# Test referencing symbols for create_user function
file_path = os.path.join("test_repo", "services.py")
# Line 15 contains the create_user function definition
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
create_user_symbol = next((s for s in symbols[0] if s.get("name") == "create_user"), None)
if not create_user_symbol or "selectionRange" not in create_user_symbol:
raise AssertionError("create_user symbol or its selectionRange not found")
@@ -131,7 +131,7 @@ class TestLanguageServerSymbols:
# Test referencing symbols for User class
file_path = os.path.join("test_repo", "models.py")
# Line 31 contains the User class definition
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
user_symbol = next((s for s in symbols[0] if s.get("name") == "User"), None)
if not user_symbol or "selectionRange" not in user_symbol:
raise AssertionError("User symbol or its selectionRange not found")
@@ -152,7 +152,7 @@ class TestLanguageServerSymbols:
# Test referencing symbols for id parameter in get_user
file_path = os.path.join("test_repo", "services.py")
# Line 24 contains the get_user method with id parameter
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
get_user_symbol = next((s for s in symbols[0] if s.get("name") == "get_user"), None)
if not get_user_symbol or "selectionRange" not in get_user_symbol:
raise AssertionError("get_user symbol or its selectionRange not found")
@@ -390,7 +390,9 @@ class TestLanguageServerSymbols:
if "location" in user_management_node and "relativePath" in user_management_node["location"]:
user_management_rel_path = user_management_node["location"]["relativePath"]
assert user_management_rel_path == os.path.join("examples", "user_management.py")
_, user_management_roots = language_server.request_document_symbols(os.path.join("examples", "user_management.py"))
_, user_management_roots = language_server.request_document_symbols(
os.path.join("examples", "user_management.py")
).get_all_symbols_and_roots()
assert user_management_roots == user_management_node["children"]
@pytest.mark.parametrize("language_server", [Language.PYTHON], indirect=True)
@@ -411,7 +413,9 @@ class TestLanguageServerSymbols:
if "location" in user_management_node and "relativePath" in user_management_node["location"]:
user_management_rel_path = user_management_node["location"]["relativePath"]
assert user_management_rel_path == os.path.join("examples", "user_management.py")
_, user_management_roots = language_server.request_document_symbols(os.path.join("examples", "user_management.py"))
_, user_management_roots = language_server.request_document_symbols(
os.path.join("examples", "user_management.py")
).get_all_symbols_and_roots()
assert user_management_roots == user_management_node["children"]
@pytest.mark.parametrize("language_server", [Language.PYTHON], indirect=True)
+1 -1
View File
@@ -27,7 +27,7 @@ class TestRLanguageServer:
@pytest.mark.parametrize("language_server", [Language.R], indirect=True)
def test_symbol_retrieval(self, language_server: SolidLanguageServer):
"""Test R document symbol extraction."""
all_symbols, _root_symbols = language_server.request_document_symbols(os.path.join("R", "utils.R"))
all_symbols, _root_symbols = language_server.request_document_symbols(os.path.join("R", "utils.R")).get_all_symbols_and_roots()
# Should find the three exported functions
function_symbols = [s for s in all_symbols if s.get("kind") == 12] # Function kind
+5 -5
View File
@@ -21,7 +21,7 @@ class TestRegoLanguageServer:
def test_request_document_symbols_authz(self, language_server: SolidLanguageServer) -> None:
"""Test that document symbols can be retrieved from authz.rego."""
file_path = os.path.join("policies", "authz.rego")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -40,7 +40,7 @@ class TestRegoLanguageServer:
def test_request_document_symbols_helpers(self, language_server: SolidLanguageServer) -> None:
"""Test that document symbols can be retrieved from helpers.rego."""
file_path = os.path.join("utils", "helpers.rego")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -71,7 +71,7 @@ class TestRegoLanguageServer:
file_path = os.path.join("policies", "authz.rego")
# Get document symbols
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
# Find the is_admin symbol which references admin_roles
@@ -98,7 +98,7 @@ class TestRegoLanguageServer:
file_path = os.path.join("policies", "authz.rego")
# Get document symbols
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
# Find the allow symbol
@@ -123,7 +123,7 @@ class TestRegoLanguageServer:
def test_find_symbols_validation(self, language_server: SolidLanguageServer) -> None:
"""Test finding symbols in validation.rego which has imports."""
file_path = os.path.join("policies", "validation.rego")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
+1 -1
View File
@@ -20,7 +20,7 @@ class TestRubyLanguageServer:
@pytest.mark.parametrize("language_server", [Language.RUBY], indirect=True)
def test_find_referencing_symbols(self, language_server: SolidLanguageServer) -> None:
file_path = os.path.join("main.rb")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
helper_symbol = None
for sym in symbols[0]:
if sym.get("name") == "helper_function":
@@ -89,7 +89,7 @@ class TestRubyLanguageServerSymbols:
"""Test request_containing_symbol for a module context."""
# Test that we can find the Services module in document symbols
file_path = os.path.join("services.rb")
symbols, _roots = language_server.request_document_symbols(file_path)
symbols, _roots = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Verify Services module appears in document symbols
services_module = None
@@ -141,7 +141,7 @@ class TestRubyLanguageServerSymbols:
# Test referencing symbols for create_user method
file_path = os.path.join("services.rb")
# Line containing the create_user method definition
symbols, _roots = language_server.request_document_symbols(file_path)
symbols, _roots = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
create_user_symbol = None
# Find create_user method in the document symbols (Ruby returns flat list)
@@ -169,7 +169,7 @@ class TestRubyLanguageServerSymbols:
# Test referencing symbols for User class
file_path = os.path.join("models.rb")
# Find User class in document symbols
symbols, _roots = language_server.request_document_symbols(file_path)
symbols, _roots = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
user_symbol = None
for symbol in symbols:
@@ -285,7 +285,7 @@ class TestRubyLanguageServerSymbols:
def test_document_symbols_detailed(self, language_server: SolidLanguageServer) -> None:
"""Test document symbols for detailed Ruby file structure."""
file_path = os.path.join("models.rb")
symbols, roots = language_server.request_document_symbols(file_path)
symbols, roots = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Verify we have symbols
assert len(symbols) > 0 or len(roots) > 0
@@ -310,7 +310,7 @@ class TestRubyLanguageServerSymbols:
def test_module_and_class_hierarchy(self, language_server: SolidLanguageServer) -> None:
"""Test symbol detection for modules and nested class hierarchies."""
file_path = os.path.join("nested.rb")
symbols, roots = language_server.request_document_symbols(file_path)
symbols, roots = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Verify we can detect the nested structure
assert len(symbols) > 0 or len(roots) > 0
@@ -363,7 +363,7 @@ class TestRubyLanguageServerSymbols:
# Test referencing symbols for a method parameter in get_user method
file_path = os.path.join("services.rb")
# Find get_user method and test parameter references
symbols, _roots = language_server.request_document_symbols(file_path)
symbols, _roots = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
get_user_symbol = None
for symbol in symbols:
+3 -3
View File
@@ -31,7 +31,7 @@ class TestRust2024EditionLanguageServer:
def test_find_references_raw(self) -> None:
# Test finding references to the 'add' function defined in main.rs
file_path = os.path.join("src", "main.rs")
symbols = self.language_server.request_document_symbols(file_path)
symbols = self.language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
add_symbol = None
for sym in symbols[0]:
if sym.get("name") == "add":
@@ -53,7 +53,7 @@ class TestRust2024EditionLanguageServer:
def test_find_referencing_symbols_multiply(self) -> None:
# Find references to 'multiply' function defined in lib.rs
file_path = os.path.join("src", "lib.rs")
symbols = self.language_server.request_document_symbols(file_path)
symbols = self.language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
multiply_symbol = None
for sym in symbols[0]:
if sym.get("name") == "multiply":
@@ -69,7 +69,7 @@ class TestRust2024EditionLanguageServer:
def test_find_calculator_struct_and_impl(self) -> None:
# Test finding the Calculator struct and its impl block
file_path = os.path.join("src", "lib.rs")
symbols = self.language_server.request_document_symbols(file_path)
symbols = self.language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
# Find the Calculator struct
calculator_struct = None
+2 -2
View File
@@ -13,7 +13,7 @@ class TestRustLanguageServer:
def test_find_references_raw(self, language_server: SolidLanguageServer) -> None:
# Directly test the request_references method for the add function
file_path = os.path.join("src", "lib.rs")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
add_symbol = None
for sym in symbols[0]:
if sym.get("name") == "add":
@@ -37,7 +37,7 @@ class TestRustLanguageServer:
def test_find_referencing_symbols(self, language_server: SolidLanguageServer) -> None:
# Find references to 'add' defined in lib.rs, should be referenced from main.rs
file_path = os.path.join("src", "lib.rs")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
add_symbol = None
for sym in symbols[0]:
if sym.get("name") == "add":
@@ -29,7 +29,7 @@ def scala_ls():
def test_scala_document_symbols(scala_ls):
"""Test document symbols for Main.scala"""
symbols, _ = scala_ls.request_document_symbols(MAIN_FILE_PATH)
symbols, _ = scala_ls.request_document_symbols(MAIN_FILE_PATH).get_all_symbols_and_roots()
symbol_names = [s["name"] for s in symbols]
assert symbol_names[0] == "com.example"
assert symbol_names[1] == "Main"
+4 -4
View File
@@ -88,7 +88,7 @@ class TestSwiftLanguageServerBasics:
# First, let's check if Utils is used anywhere (it might not be in this simple test)
# We'll test goto_definition on Utils struct itself
symbols = language_server.request_document_symbols(utils_file)
symbols = language_server.request_document_symbols(utils_file).get_all_symbols_and_roots()
utils_symbol = next((s for s in symbols[0] if s.get("name") == "Utils"), None)
sel_start = utils_symbol["selectionRange"]["start"]
@@ -104,7 +104,7 @@ class TestSwiftLanguageServerBasics:
"""Test request_references on the Calculator class."""
# Get references to the Calculator class in main.swift
file_path = os.path.join("src", "main.swift")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
calculator_symbol = next((s for s in symbols[0] if s.get("name") == "Calculator"), None)
@@ -126,7 +126,7 @@ class TestSwiftLanguageServerBasics:
"""Test request_references on the User struct."""
# Get references to the User struct in main.swift
file_path = os.path.join("src", "main.swift")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
user_symbol = next((s for s in symbols[0] if s.get("name") == "User"), None)
@@ -147,7 +147,7 @@ class TestSwiftLanguageServerBasics:
"""Test request_references on the Utils struct."""
# Get references to the Utils struct in utils.swift
file_path = os.path.join("src", "utils.swift")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
utils_symbol = next((s for s in symbols[0] if s.get("name") == "Utils"), None)
if not utils_symbol or "selectionRange" not in utils_symbol:
raise AssertionError("Utils symbol or its selectionRange not found")
@@ -21,7 +21,7 @@ class TestLanguageServerBasics:
# Simple test to verify the language server is working
file_path = "main.tf"
# Just try to get document symbols - this should work without hanging
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
assert len(symbols) > 0, "Should find at least some symbols in main.tf"
@pytest.mark.parametrize("language_server", [Language.TERRAFORM], indirect=True)
@@ -30,7 +30,7 @@ class TestLanguageServerBasics:
# Get references to an aws_instance resource in main.tf
file_path = "main.tf"
# Find aws_instance resources
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
aws_instance_symbol = next((s for s in symbols[0] if s.get("name") == 'resource "aws_instance" "web_server"'), None)
if not aws_instance_symbol or "selectionRange" not in aws_instance_symbol:
raise AssertionError("aws_instance symbol or its selectionRange not found")
@@ -44,7 +44,7 @@ class TestLanguageServerBasics:
# Get references to a variable in variables.tf
file_path = "variables.tf"
# Find variable definitions
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
var_symbol = next((s for s in symbols[0] if s.get("name") == 'variable "instance_type"'), None)
if not var_symbol or "selectionRange" not in var_symbol:
raise AssertionError("variable symbol or its selectionRange not found")
@@ -19,7 +19,7 @@ class TestTypescriptLanguageServer:
@pytest.mark.parametrize("language_server", [Language.TYPESCRIPT], indirect=True)
def test_find_referencing_symbols(self, language_server: SolidLanguageServer) -> None:
file_path = os.path.join("index.ts")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
helper_symbol = None
for sym in symbols[0]:
if sym.get("name") == "helperFunction":
+9 -9
View File
@@ -30,7 +30,7 @@ class TestZigLanguageServer:
def test_find_symbols_in_main(self, language_server: SolidLanguageServer) -> None:
"""Test finding specific symbols in main.zig."""
file_path = os.path.join("src", "main.zig")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -47,7 +47,7 @@ class TestZigLanguageServer:
def test_find_symbols_in_calculator(self, language_server: SolidLanguageServer) -> None:
"""Test finding Calculator struct and its methods."""
file_path = os.path.join("src", "calculator.zig")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -90,7 +90,7 @@ class TestZigLanguageServer:
def test_find_symbols_in_math_utils(self, language_server: SolidLanguageServer) -> None:
"""Test finding functions in math_utils.zig."""
file_path = os.path.join("src", "math_utils.zig")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
assert symbols is not None
assert len(symbols) > 0
@@ -106,7 +106,7 @@ class TestZigLanguageServer:
def test_find_references_within_file(self, language_server: SolidLanguageServer) -> None:
"""Test finding references within the same file."""
file_path = os.path.join("src", "calculator.zig")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
@@ -163,7 +163,7 @@ class TestZigLanguageServer:
time.sleep(1)
# Find Calculator struct
symbols = language_server.request_document_symbols(os.path.join("src", "calculator.zig"))
symbols = language_server.request_document_symbols(os.path.join("src", "calculator.zig")).get_all_symbols_and_roots()
symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
calculator_symbol = None
@@ -207,7 +207,7 @@ class TestZigLanguageServer:
"""
# Find references to Calculator from calculator.zig
file_path = os.path.join("src", "calculator.zig")
symbols = language_server.request_document_symbols(file_path)
symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()
symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
calculator_symbol = None
@@ -291,7 +291,7 @@ class TestZigLanguageServer:
def test_verify_cross_file_imports(self, language_server: SolidLanguageServer) -> None:
"""Verify that our test files have proper cross-file imports."""
# Verify main.zig imports
main_symbols = language_server.request_document_symbols(os.path.join("src", "main.zig"))
main_symbols = language_server.request_document_symbols(os.path.join("src", "main.zig")).get_all_symbols_and_roots()
assert main_symbols is not None
main_list = main_symbols[0] if isinstance(main_symbols, tuple) else main_symbols
main_names = {sym.get("name") for sym in main_list if isinstance(sym, dict)}
@@ -301,14 +301,14 @@ class TestZigLanguageServer:
assert "greeting" in main_names, "greeting function should be in main.zig"
# Verify calculator.zig exports Calculator
calc_symbols = language_server.request_document_symbols(os.path.join("src", "calculator.zig"))
calc_symbols = language_server.request_document_symbols(os.path.join("src", "calculator.zig")).get_all_symbols_and_roots()
assert calc_symbols is not None
calc_list = calc_symbols[0] if isinstance(calc_symbols, tuple) else calc_symbols
calc_names = {sym.get("name") for sym in calc_list if isinstance(sym, dict)}
assert "Calculator" in calc_names, "Calculator struct should be in calculator.zig"
# Verify math_utils.zig exports functions
math_symbols = language_server.request_document_symbols(os.path.join("src", "math_utils.zig"))
math_symbols = language_server.request_document_symbols(os.path.join("src", "math_utils.zig")).get_all_symbols_and_roots()
assert math_symbols is not None
math_list = math_symbols[0] if isinstance(math_symbols, tuple) else math_symbols
math_names = {sym.get("name") for sym in math_list if isinstance(sym, dict)}