#
tokens: 49660/50000 18/413 files (page 5/17)
lines: off (toggle) GitHub
raw markdown copy
This is page 5 of 17. Use http://codebase.md/oraios/serena?page={x} to view the full context.

# Directory Structure

```
├── .devcontainer
│   └── devcontainer.json
├── .dockerignore
├── .env.example
├── .github
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE
│   │   ├── config.yml
│   │   ├── feature_request.md
│   │   └── issue--bug--performance-problem--question-.md
│   └── workflows
│       ├── codespell.yml
│       ├── docker.yml
│       ├── docs.yaml
│       ├── junie.yml
│       ├── publish.yml
│       └── pytest.yml
├── .gitignore
├── .serena
│   ├── .gitignore
│   ├── memories
│   │   ├── adding_new_language_support_guide.md
│   │   ├── serena_core_concepts_and_architecture.md
│   │   ├── serena_repository_structure.md
│   │   └── suggested_commands.md
│   └── project.yml
├── .vscode
│   └── settings.json
├── CHANGELOG.md
├── CLAUDE.md
├── compose.yaml
├── CONTRIBUTING.md
├── docker_build_and_run.sh
├── DOCKER.md
├── Dockerfile
├── docs
│   ├── _config.yml
│   ├── _static
│   │   └── images
│   │       └── jetbrains-marketplace-button.png
│   ├── .gitignore
│   ├── 01-about
│   │   ├── 000_intro.md
│   │   ├── 010_llm-integration.md
│   │   ├── 020_programming-languages.md
│   │   ├── 030_serena-in-action.md
│   │   ├── 035_tools.md
│   │   ├── 040_comparison-to-other-agents.md
│   │   └── 050_acknowledgements.md
│   ├── 02-usage
│   │   ├── 000_intro.md
│   │   ├── 010_prerequisites.md
│   │   ├── 020_running.md
│   │   ├── 025_jetbrains_plugin.md
│   │   ├── 030_clients.md
│   │   ├── 040_workflow.md
│   │   ├── 050_configuration.md
│   │   ├── 060_dashboard.md
│   │   ├── 070_security.md
│   │   └── 999_additional-usage.md
│   ├── 03-special-guides
│   │   ├── 000_intro.md
│   │   ├── custom_agent.md
│   │   ├── groovy_setup_guide_for_serena.md
│   │   ├── scala_setup_guide_for_serena.md
│   │   └── serena_on_chatgpt.md
│   ├── autogen_rst.py
│   ├── create_toc.py
│   └── index.md
├── flake.lock
├── flake.nix
├── lessons_learned.md
├── LICENSE
├── llms-install.md
├── pyproject.toml
├── README.md
├── repo_dir_sync.py
├── resources
│   ├── jetbrains-marketplace-button.cdr
│   ├── serena-icons.cdr
│   ├── serena-logo-dark-mode.svg
│   ├── serena-logo.cdr
│   ├── serena-logo.svg
│   └── vscode_sponsor_logo.png
├── roadmap.md
├── scripts
│   ├── agno_agent.py
│   ├── demo_run_tools.py
│   ├── gen_prompt_factory.py
│   ├── mcp_server.py
│   ├── print_mode_context_options.py
│   ├── print_tool_overview.py
│   └── profile_tool_call.py
├── src
│   ├── interprompt
│   │   ├── __init__.py
│   │   ├── .syncCommitId.remote
│   │   ├── .syncCommitId.this
│   │   ├── jinja_template.py
│   │   ├── multilang_prompt.py
│   │   ├── prompt_factory.py
│   │   └── util
│   │       ├── __init__.py
│   │       └── class_decorators.py
│   ├── README.md
│   ├── serena
│   │   ├── __init__.py
│   │   ├── agent.py
│   │   ├── agno.py
│   │   ├── analytics.py
│   │   ├── cli.py
│   │   ├── code_editor.py
│   │   ├── config
│   │   │   ├── __init__.py
│   │   │   ├── context_mode.py
│   │   │   └── serena_config.py
│   │   ├── constants.py
│   │   ├── dashboard.py
│   │   ├── generated
│   │   │   └── generated_prompt_factory.py
│   │   ├── gui_log_viewer.py
│   │   ├── ls_manager.py
│   │   ├── mcp.py
│   │   ├── project.py
│   │   ├── prompt_factory.py
│   │   ├── resources
│   │   │   ├── config
│   │   │   │   ├── contexts
│   │   │   │   │   ├── agent.yml
│   │   │   │   │   ├── chatgpt.yml
│   │   │   │   │   ├── claude-code.yml
│   │   │   │   │   ├── codex.yml
│   │   │   │   │   ├── context.template.yml
│   │   │   │   │   ├── desktop-app.yml
│   │   │   │   │   ├── ide.yml
│   │   │   │   │   └── oaicompat-agent.yml
│   │   │   │   ├── internal_modes
│   │   │   │   │   └── jetbrains.yml
│   │   │   │   ├── modes
│   │   │   │   │   ├── editing.yml
│   │   │   │   │   ├── interactive.yml
│   │   │   │   │   ├── mode.template.yml
│   │   │   │   │   ├── no-memories.yml
│   │   │   │   │   ├── no-onboarding.yml
│   │   │   │   │   ├── onboarding.yml
│   │   │   │   │   ├── one-shot.yml
│   │   │   │   │   └── planning.yml
│   │   │   │   └── prompt_templates
│   │   │   │       ├── simple_tool_outputs.yml
│   │   │   │       └── system_prompt.yml
│   │   │   ├── dashboard
│   │   │   │   ├── dashboard.css
│   │   │   │   ├── dashboard.js
│   │   │   │   ├── index.html
│   │   │   │   ├── jquery.min.js
│   │   │   │   ├── news
│   │   │   │   │   └── 20260111.html
│   │   │   │   ├── serena-icon-16.png
│   │   │   │   ├── serena-icon-32.png
│   │   │   │   ├── serena-icon-48.png
│   │   │   │   ├── serena-logo-dark-mode.svg
│   │   │   │   ├── serena-logo.svg
│   │   │   │   ├── serena-logs-dark-mode.png
│   │   │   │   └── serena-logs.png
│   │   │   ├── project.template.yml
│   │   │   └── serena_config.template.yml
│   │   ├── symbol.py
│   │   ├── task_executor.py
│   │   ├── text_utils.py
│   │   ├── tools
│   │   │   ├── __init__.py
│   │   │   ├── cmd_tools.py
│   │   │   ├── config_tools.py
│   │   │   ├── file_tools.py
│   │   │   ├── jetbrains_plugin_client.py
│   │   │   ├── jetbrains_tools.py
│   │   │   ├── jetbrains_types.py
│   │   │   ├── memory_tools.py
│   │   │   ├── symbol_tools.py
│   │   │   ├── tools_base.py
│   │   │   └── workflow_tools.py
│   │   └── util
│   │       ├── class_decorators.py
│   │       ├── cli_util.py
│   │       ├── exception.py
│   │       ├── file_system.py
│   │       ├── general.py
│   │       ├── git.py
│   │       ├── gui.py
│   │       ├── inspection.py
│   │       ├── logging.py
│   │       ├── shell.py
│   │       ├── thread.py
│   │       └── version.py
│   └── solidlsp
│       ├── __init__.py
│       ├── .gitignore
│       ├── language_servers
│       │   ├── al_language_server.py
│       │   ├── bash_language_server.py
│       │   ├── clangd_language_server.py
│       │   ├── clojure_lsp.py
│       │   ├── common.py
│       │   ├── csharp_language_server.py
│       │   ├── dart_language_server.py
│       │   ├── eclipse_jdtls.py
│       │   ├── elixir_tools
│       │   │   ├── __init__.py
│       │   │   ├── elixir_tools.py
│       │   │   └── README.md
│       │   ├── elm_language_server.py
│       │   ├── erlang_language_server.py
│       │   ├── fortran_language_server.py
│       │   ├── fsharp_language_server.py
│       │   ├── gopls.py
│       │   ├── groovy_language_server.py
│       │   ├── haskell_language_server.py
│       │   ├── intelephense.py
│       │   ├── jedi_server.py
│       │   ├── julia_server.py
│       │   ├── kotlin_language_server.py
│       │   ├── lua_ls.py
│       │   ├── marksman.py
│       │   ├── matlab_language_server.py
│       │   ├── nixd_ls.py
│       │   ├── omnisharp
│       │   │   ├── initialize_params.json
│       │   │   ├── runtime_dependencies.json
│       │   │   └── workspace_did_change_configuration.json
│       │   ├── omnisharp.py
│       │   ├── pascal_server.py
│       │   ├── perl_language_server.py
│       │   ├── powershell_language_server.py
│       │   ├── pyright_server.py
│       │   ├── r_language_server.py
│       │   ├── regal_server.py
│       │   ├── ruby_lsp.py
│       │   ├── rust_analyzer.py
│       │   ├── scala_language_server.py
│       │   ├── solargraph.py
│       │   ├── sourcekit_lsp.py
│       │   ├── taplo_server.py
│       │   ├── terraform_ls.py
│       │   ├── typescript_language_server.py
│       │   ├── vts_language_server.py
│       │   ├── vue_language_server.py
│       │   ├── yaml_language_server.py
│       │   └── zls.py
│       ├── ls_config.py
│       ├── ls_exceptions.py
│       ├── ls_handler.py
│       ├── ls_request.py
│       ├── ls_types.py
│       ├── ls_utils.py
│       ├── ls.py
│       ├── lsp_protocol_handler
│       │   ├── lsp_constants.py
│       │   ├── lsp_requests.py
│       │   ├── lsp_types.py
│       │   └── server.py
│       ├── settings.py
│       └── util
│           ├── cache.py
│           ├── subprocess_util.py
│           └── zip.py
├── sync.py
├── test
│   ├── __init__.py
│   ├── conftest.py
│   ├── resources
│   │   └── repos
│   │       ├── al
│   │       │   └── test_repo
│   │       │       ├── app.json
│   │       │       └── src
│   │       │           ├── Codeunits
│   │       │           │   ├── CustomerMgt.Codeunit.al
│   │       │           │   └── PaymentProcessorImpl.Codeunit.al
│   │       │           ├── Enums
│   │       │           │   └── CustomerType.Enum.al
│   │       │           ├── Interfaces
│   │       │           │   └── IPaymentProcessor.Interface.al
│   │       │           ├── Pages
│   │       │           │   ├── CustomerCard.Page.al
│   │       │           │   └── CustomerList.Page.al
│   │       │           ├── TableExtensions
│   │       │           │   └── Item.TableExt.al
│   │       │           └── Tables
│   │       │               └── Customer.Table.al
│   │       ├── bash
│   │       │   └── test_repo
│   │       │       ├── config.sh
│   │       │       ├── main.sh
│   │       │       └── utils.sh
│   │       ├── clojure
│   │       │   └── test_repo
│   │       │       ├── deps.edn
│   │       │       └── src
│   │       │           └── test_app
│   │       │               ├── core.clj
│   │       │               └── utils.clj
│   │       ├── csharp
│   │       │   └── test_repo
│   │       │       ├── .gitignore
│   │       │       ├── Models
│   │       │       │   └── Person.cs
│   │       │       ├── Program.cs
│   │       │       ├── serena.sln
│   │       │       └── TestProject.csproj
│   │       ├── dart
│   │       │   └── test_repo
│   │       │       ├── .gitignore
│   │       │       ├── lib
│   │       │       │   ├── helper.dart
│   │       │       │   ├── main.dart
│   │       │       │   └── models.dart
│   │       │       └── pubspec.yaml
│   │       ├── elixir
│   │       │   └── test_repo
│   │       │       ├── .gitignore
│   │       │       ├── lib
│   │       │       │   ├── examples.ex
│   │       │       │   ├── ignored_dir
│   │       │       │   │   └── ignored_module.ex
│   │       │       │   ├── models.ex
│   │       │       │   ├── services.ex
│   │       │       │   ├── test_repo.ex
│   │       │       │   └── utils.ex
│   │       │       ├── mix.exs
│   │       │       ├── mix.lock
│   │       │       ├── scripts
│   │       │       │   └── build_script.ex
│   │       │       └── test
│   │       │           ├── models_test.exs
│   │       │           └── test_repo_test.exs
│   │       ├── elm
│   │       │   └── test_repo
│   │       │       ├── elm.json
│   │       │       ├── Main.elm
│   │       │       └── Utils.elm
│   │       ├── erlang
│   │       │   └── test_repo
│   │       │       ├── hello.erl
│   │       │       ├── ignored_dir
│   │       │       │   └── ignored_module.erl
│   │       │       ├── include
│   │       │       │   ├── records.hrl
│   │       │       │   └── types.hrl
│   │       │       ├── math_utils.erl
│   │       │       ├── rebar.config
│   │       │       ├── src
│   │       │       │   ├── app.erl
│   │       │       │   ├── models.erl
│   │       │       │   ├── services.erl
│   │       │       │   └── utils.erl
│   │       │       └── test
│   │       │           ├── models_tests.erl
│   │       │           └── utils_tests.erl
│   │       ├── fortran
│   │       │   └── test_repo
│   │       │       ├── main.f90
│   │       │       └── modules
│   │       │           ├── geometry.f90
│   │       │           └── math_utils.f90
│   │       ├── fsharp
│   │       │   └── test_repo
│   │       │       ├── .gitignore
│   │       │       ├── Calculator.fs
│   │       │       ├── Models
│   │       │       │   └── Person.fs
│   │       │       ├── Program.fs
│   │       │       ├── README.md
│   │       │       └── TestProject.fsproj
│   │       ├── go
│   │       │   └── test_repo
│   │       │       └── main.go
│   │       ├── groovy
│   │       │   └── test_repo
│   │       │       ├── .gitignore
│   │       │       ├── build.gradle
│   │       │       └── src
│   │       │           └── main
│   │       │               └── groovy
│   │       │                   └── com
│   │       │                       └── example
│   │       │                           ├── Main.groovy
│   │       │                           ├── Model.groovy
│   │       │                           ├── ModelUser.groovy
│   │       │                           └── Utils.groovy
│   │       ├── haskell
│   │       │   └── test_repo
│   │       │       ├── app
│   │       │       │   └── Main.hs
│   │       │       ├── haskell-test-repo.cabal
│   │       │       ├── package.yaml
│   │       │       ├── src
│   │       │       │   ├── Calculator.hs
│   │       │       │   └── Helper.hs
│   │       │       └── stack.yaml
│   │       ├── java
│   │       │   └── test_repo
│   │       │       ├── pom.xml
│   │       │       └── src
│   │       │           └── main
│   │       │               └── java
│   │       │                   └── test_repo
│   │       │                       ├── Main.java
│   │       │                       ├── Model.java
│   │       │                       ├── ModelUser.java
│   │       │                       └── Utils.java
│   │       ├── julia
│   │       │   └── test_repo
│   │       │       ├── lib
│   │       │       │   └── helper.jl
│   │       │       └── main.jl
│   │       ├── kotlin
│   │       │   └── test_repo
│   │       │       ├── .gitignore
│   │       │       ├── build.gradle.kts
│   │       │       └── src
│   │       │           └── main
│   │       │               └── kotlin
│   │       │                   └── test_repo
│   │       │                       ├── Main.kt
│   │       │                       ├── Model.kt
│   │       │                       ├── ModelUser.kt
│   │       │                       └── Utils.kt
│   │       ├── lua
│   │       │   └── test_repo
│   │       │       ├── .gitignore
│   │       │       ├── main.lua
│   │       │       ├── src
│   │       │       │   ├── calculator.lua
│   │       │       │   └── utils.lua
│   │       │       └── tests
│   │       │           └── test_calculator.lua
│   │       ├── markdown
│   │       │   └── test_repo
│   │       │       ├── api.md
│   │       │       ├── CONTRIBUTING.md
│   │       │       ├── guide.md
│   │       │       └── README.md
│   │       ├── matlab
│   │       │   └── test_repo
│   │       │       ├── Calculator.m
│   │       │       └── main.m
│   │       ├── nix
│   │       │   └── test_repo
│   │       │       ├── .gitignore
│   │       │       ├── default.nix
│   │       │       ├── flake.nix
│   │       │       ├── lib
│   │       │       │   └── utils.nix
│   │       │       ├── modules
│   │       │       │   └── example.nix
│   │       │       └── scripts
│   │       │           └── hello.sh
│   │       ├── pascal
│   │       │   └── test_repo
│   │       │       ├── .gitignore
│   │       │       ├── lib
│   │       │       │   └── helper.pas
│   │       │       └── main.pas
│   │       ├── perl
│   │       │   └── test_repo
│   │       │       ├── helper.pl
│   │       │       └── main.pl
│   │       ├── php
│   │       │   └── test_repo
│   │       │       ├── helper.php
│   │       │       ├── index.php
│   │       │       └── simple_var.php
│   │       ├── powershell
│   │       │   └── test_repo
│   │       │       ├── main.ps1
│   │       │       ├── PowerShellEditorServices.json
│   │       │       └── utils.ps1
│   │       ├── python
│   │       │   └── test_repo
│   │       │       ├── .gitignore
│   │       │       ├── custom_test
│   │       │       │   ├── __init__.py
│   │       │       │   └── advanced_features.py
│   │       │       ├── examples
│   │       │       │   ├── __init__.py
│   │       │       │   └── user_management.py
│   │       │       ├── ignore_this_dir_with_postfix
│   │       │       │   └── ignored_module.py
│   │       │       ├── scripts
│   │       │       │   ├── __init__.py
│   │       │       │   └── run_app.py
│   │       │       └── test_repo
│   │       │           ├── __init__.py
│   │       │           ├── complex_types.py
│   │       │           ├── models.py
│   │       │           ├── name_collisions.py
│   │       │           ├── nested_base.py
│   │       │           ├── nested.py
│   │       │           ├── overloaded.py
│   │       │           ├── services.py
│   │       │           ├── utils.py
│   │       │           └── variables.py
│   │       ├── r
│   │       │   └── test_repo
│   │       │       ├── .Rbuildignore
│   │       │       ├── DESCRIPTION
│   │       │       ├── examples
│   │       │       │   └── analysis.R
│   │       │       ├── NAMESPACE
│   │       │       └── R
│   │       │           ├── models.R
│   │       │           └── utils.R
│   │       ├── rego
│   │       │   └── test_repo
│   │       │       ├── policies
│   │       │       │   ├── authz.rego
│   │       │       │   └── validation.rego
│   │       │       └── utils
│   │       │           └── helpers.rego
│   │       ├── ruby
│   │       │   └── test_repo
│   │       │       ├── .solargraph.yml
│   │       │       ├── examples
│   │       │       │   └── user_management.rb
│   │       │       ├── lib.rb
│   │       │       ├── main.rb
│   │       │       ├── models.rb
│   │       │       ├── nested.rb
│   │       │       ├── services.rb
│   │       │       └── variables.rb
│   │       ├── rust
│   │       │   ├── test_repo
│   │       │   │   ├── Cargo.lock
│   │       │   │   ├── Cargo.toml
│   │       │   │   └── src
│   │       │   │       ├── lib.rs
│   │       │   │       └── main.rs
│   │       │   └── test_repo_2024
│   │       │       ├── Cargo.lock
│   │       │       ├── Cargo.toml
│   │       │       └── src
│   │       │           ├── lib.rs
│   │       │           └── main.rs
│   │       ├── scala
│   │       │   ├── build.sbt
│   │       │   ├── project
│   │       │   │   ├── build.properties
│   │       │   │   ├── metals.sbt
│   │       │   │   └── plugins.sbt
│   │       │   └── src
│   │       │       └── main
│   │       │           └── scala
│   │       │               └── com
│   │       │                   └── example
│   │       │                       ├── Main.scala
│   │       │                       └── Utils.scala
│   │       ├── swift
│   │       │   └── test_repo
│   │       │       ├── Package.swift
│   │       │       └── src
│   │       │           ├── main.swift
│   │       │           └── utils.swift
│   │       ├── terraform
│   │       │   └── test_repo
│   │       │       ├── data.tf
│   │       │       ├── main.tf
│   │       │       ├── outputs.tf
│   │       │       └── variables.tf
│   │       ├── toml
│   │       │   └── test_repo
│   │       │       ├── Cargo.toml
│   │       │       ├── config.toml
│   │       │       └── pyproject.toml
│   │       ├── typescript
│   │       │   └── test_repo
│   │       │       ├── .serena
│   │       │       │   └── project.yml
│   │       │       ├── index.ts
│   │       │       ├── tsconfig.json
│   │       │       ├── use_helper.ts
│   │       │       └── ws_manager.js
│   │       ├── vue
│   │       │   └── test_repo
│   │       │       ├── .gitignore
│   │       │       ├── index.html
│   │       │       ├── package.json
│   │       │       ├── src
│   │       │       │   ├── App.vue
│   │       │       │   ├── components
│   │       │       │   │   ├── CalculatorButton.vue
│   │       │       │   │   ├── CalculatorDisplay.vue
│   │       │       │   │   └── CalculatorInput.vue
│   │       │       │   ├── composables
│   │       │       │   │   ├── useFormatter.ts
│   │       │       │   │   └── useTheme.ts
│   │       │       │   ├── main.ts
│   │       │       │   ├── stores
│   │       │       │   │   └── calculator.ts
│   │       │       │   └── types
│   │       │       │       └── index.ts
│   │       │       ├── tsconfig.json
│   │       │       ├── tsconfig.node.json
│   │       │       └── vite.config.ts
│   │       ├── yaml
│   │       │   └── test_repo
│   │       │       ├── config.yaml
│   │       │       ├── data.yaml
│   │       │       └── services.yml
│   │       └── zig
│   │           └── test_repo
│   │               ├── .gitignore
│   │               ├── build.zig
│   │               ├── src
│   │               │   ├── calculator.zig
│   │               │   ├── main.zig
│   │               │   └── math_utils.zig
│   │               └── zls.json
│   ├── serena
│   │   ├── __init__.py
│   │   ├── __snapshots__
│   │   │   └── test_symbol_editing.ambr
│   │   ├── config
│   │   │   ├── __init__.py
│   │   │   └── test_serena_config.py
│   │   ├── test_cli_project_commands.py
│   │   ├── test_edit_marker.py
│   │   ├── test_mcp.py
│   │   ├── test_serena_agent.py
│   │   ├── test_symbol_editing.py
│   │   ├── test_symbol.py
│   │   ├── test_task_executor.py
│   │   ├── test_text_utils.py
│   │   ├── test_tool_parameter_types.py
│   │   └── util
│   │       ├── test_exception.py
│   │       └── test_file_system.py
│   └── solidlsp
│       ├── al
│       │   └── test_al_basic.py
│       ├── bash
│       │   ├── __init__.py
│       │   └── test_bash_basic.py
│       ├── clojure
│       │   ├── __init__.py
│       │   └── test_clojure_basic.py
│       ├── csharp
│       │   └── test_csharp_basic.py
│       ├── dart
│       │   ├── __init__.py
│       │   └── test_dart_basic.py
│       ├── elixir
│       │   ├── __init__.py
│       │   ├── conftest.py
│       │   ├── test_elixir_basic.py
│       │   ├── test_elixir_ignored_dirs.py
│       │   ├── test_elixir_integration.py
│       │   └── test_elixir_symbol_retrieval.py
│       ├── elm
│       │   └── test_elm_basic.py
│       ├── erlang
│       │   ├── __init__.py
│       │   ├── conftest.py
│       │   ├── test_erlang_basic.py
│       │   ├── test_erlang_ignored_dirs.py
│       │   └── test_erlang_symbol_retrieval.py
│       ├── fortran
│       │   ├── __init__.py
│       │   └── test_fortran_basic.py
│       ├── fsharp
│       │   └── test_fsharp_basic.py
│       ├── go
│       │   └── test_go_basic.py
│       ├── groovy
│       │   └── test_groovy_basic.py
│       ├── haskell
│       │   ├── __init__.py
│       │   └── test_haskell_basic.py
│       ├── java
│       │   └── test_java_basic.py
│       ├── julia
│       │   └── test_julia_basic.py
│       ├── kotlin
│       │   └── test_kotlin_basic.py
│       ├── lua
│       │   └── test_lua_basic.py
│       ├── markdown
│       │   ├── __init__.py
│       │   └── test_markdown_basic.py
│       ├── matlab
│       │   ├── __init__.py
│       │   └── test_matlab_basic.py
│       ├── nix
│       │   └── test_nix_basic.py
│       ├── pascal
│       │   ├── __init__.py
│       │   └── test_pascal_basic.py
│       ├── perl
│       │   └── test_perl_basic.py
│       ├── php
│       │   └── test_php_basic.py
│       ├── powershell
│       │   ├── __init__.py
│       │   └── test_powershell_basic.py
│       ├── python
│       │   ├── test_python_basic.py
│       │   ├── test_retrieval_with_ignored_dirs.py
│       │   └── test_symbol_retrieval.py
│       ├── r
│       │   ├── __init__.py
│       │   └── test_r_basic.py
│       ├── rego
│       │   └── test_rego_basic.py
│       ├── ruby
│       │   ├── test_ruby_basic.py
│       │   └── test_ruby_symbol_retrieval.py
│       ├── rust
│       │   ├── test_rust_2024_edition.py
│       │   ├── test_rust_analyzer_detection.py
│       │   └── test_rust_basic.py
│       ├── scala
│       │   └── test_scala_language_server.py
│       ├── swift
│       │   └── test_swift_basic.py
│       ├── terraform
│       │   └── test_terraform_basic.py
│       ├── test_lsp_protocol_handler_server.py
│       ├── toml
│       │   ├── __init__.py
│       │   ├── test_toml_basic.py
│       │   ├── test_toml_edge_cases.py
│       │   ├── test_toml_ignored_dirs.py
│       │   └── test_toml_symbol_retrieval.py
│       ├── typescript
│       │   └── test_typescript_basic.py
│       ├── util
│       │   └── test_zip.py
│       ├── vue
│       │   ├── __init__.py
│       │   ├── test_vue_basic.py
│       │   ├── test_vue_error_cases.py
│       │   ├── test_vue_rename.py
│       │   └── test_vue_symbol_retrieval.py
│       ├── yaml_ls
│       │   ├── __init__.py
│       │   └── test_yaml_basic.py
│       └── zig
│           └── test_zig_basic.py
└── uv.lock
```

# Files

--------------------------------------------------------------------------------
/test/solidlsp/powershell/test_powershell_basic.py:
--------------------------------------------------------------------------------

```python
"""
Basic integration tests for the PowerShell language server functionality.

These tests validate the functionality of the language server APIs
like request_document_symbols using the PowerShell test repository.
"""

import pytest

from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language


@pytest.mark.powershell
class TestPowerShellLanguageServerBasics:
    """Test basic functionality of the PowerShell language server."""

    @pytest.mark.parametrize("language_server", [Language.POWERSHELL], indirect=True)
    def test_powershell_language_server_initialization(self, language_server: SolidLanguageServer) -> None:
        """Test that PowerShell language server can be initialized successfully."""
        assert language_server is not None
        assert language_server.language == Language.POWERSHELL

    @pytest.mark.parametrize("language_server", [Language.POWERSHELL], indirect=True)
    def test_powershell_request_document_symbols(self, language_server: SolidLanguageServer) -> None:
        """Test request_document_symbols for PowerShell files."""
        # Test getting symbols from main.ps1
        all_symbols, _root_symbols = language_server.request_document_symbols("main.ps1").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]
        function_names = [symbol["name"] for symbol in function_symbols]

        # PSES returns function names in format "function FuncName ()" - check for function name substring
        def has_function(name: str) -> bool:
            return any(name in fn for fn in function_names)

        # Should detect the main functions from main.ps1
        assert has_function("Greet-User"), f"Should find Greet-User function in {function_names}"
        assert has_function("Process-Items"), f"Should find Process-Items function in {function_names}"
        assert has_function("Main"), f"Should find Main function in {function_names}"
        assert len(function_symbols) >= 3, f"Should find at least 3 functions, found {len(function_symbols)}"

    @pytest.mark.parametrize("language_server", [Language.POWERSHELL], indirect=True)
    def test_powershell_utils_functions(self, language_server: SolidLanguageServer) -> None:
        """Test function detection in utils.ps1 file."""
        # Test with utils.ps1
        utils_all_symbols, _utils_root_symbols = language_server.request_document_symbols("utils.ps1").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]

        # PSES returns function names in format "function FuncName ()" - check for function name substring
        def has_function(name: str) -> bool:
            return any(name in fn for fn in utils_function_names)

        # Should detect functions from utils.ps1
        expected_utils_functions = [
            "Convert-ToUpperCase",
            "Convert-ToLowerCase",
            "Remove-Whitespace",
            "Backup-File",
            "Test-ArrayContains",
            "Write-LogMessage",
            "Test-ValidEmail",
            "Test-IsNumber",
        ]

        for func_name in expected_utils_functions:
            assert has_function(func_name), f"Should find {func_name} function in utils.ps1, got {utils_function_names}"

        assert len(utils_function_symbols) >= 8, f"Should find at least 8 functions in utils.ps1, found {len(utils_function_symbols)}"

    @pytest.mark.parametrize("language_server", [Language.POWERSHELL], indirect=True)
    def test_powershell_function_with_parameters(self, language_server: SolidLanguageServer) -> None:
        """Test that functions with CmdletBinding and parameters are detected correctly."""
        all_symbols, _root_symbols = language_server.request_document_symbols("main.ps1").get_all_symbols_and_roots()

        function_symbols = [symbol for symbol in all_symbols if symbol.get("kind") == 12]

        # Find Greet-User function which has parameters
        # PSES returns function names in format "function FuncName ()"
        greet_user_symbol = next((sym for sym in function_symbols if "Greet-User" in sym["name"]), None)
        assert greet_user_symbol is not None, f"Should find Greet-User function in {[s['name'] for s in function_symbols]}"

        # Find Process-Items function which has array parameter
        process_items_symbol = next((sym for sym in function_symbols if "Process-Items" in sym["name"]), None)
        assert process_items_symbol is not None, f"Should find Process-Items function in {[s['name'] for s in function_symbols]}"

    @pytest.mark.parametrize("language_server", [Language.POWERSHELL], indirect=True)
    def test_powershell_all_function_detection(self, language_server: SolidLanguageServer) -> None:
        """Test that all expected functions are detected across both files."""
        # Get symbols from main.ps1
        main_all_symbols, _main_root_symbols = language_server.request_document_symbols("main.ps1").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]

        # Get symbols from utils.ps1
        utils_all_symbols, _utils_root_symbols = language_server.request_document_symbols("utils.ps1").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]

        # PSES returns function names in format "function FuncName ()" - check for function name substring
        def has_main_function(name: str) -> bool:
            return any(name in fn for fn in main_function_names)

        def has_utils_function(name: str) -> bool:
            return any(name in fn for fn in utils_function_names)

        # Verify main.ps1 functions
        expected_main = ["Greet-User", "Process-Items", "Main"]
        for expected_func in expected_main:
            assert has_main_function(expected_func), f"Should detect {expected_func} function in main.ps1, got {main_function_names}"

        # Verify utils.ps1 functions
        expected_utils = [
            "Convert-ToUpperCase",
            "Convert-ToLowerCase",
            "Remove-Whitespace",
            "Backup-File",
            "Test-ArrayContains",
            "Write-LogMessage",
            "Test-ValidEmail",
            "Test-IsNumber",
        ]
        for expected_func in expected_utils:
            assert has_utils_function(expected_func), f"Should detect {expected_func} function in utils.ps1, got {utils_function_names}"

        # Verify total counts
        assert len(main_functions) >= 3, f"Should find at least 3 functions in main.ps1, found {len(main_functions)}"
        assert len(utils_functions) >= 8, f"Should find at least 8 functions in utils.ps1, found {len(utils_functions)}"

    @pytest.mark.parametrize("language_server", [Language.POWERSHELL], indirect=True)
    def test_powershell_find_references_within_file(self, language_server: SolidLanguageServer) -> None:
        """Test finding references to a function within the same file."""
        main_path = "main.ps1"

        # Get symbols to find the Greet-User function which is called from Main
        all_symbols, _root_symbols = language_server.request_document_symbols(main_path).get_all_symbols_and_roots()

        # Find Greet-User function definition
        function_symbols = [s for s in all_symbols if s.get("kind") == 12]
        greet_user_symbol = next((s for s in function_symbols if "Greet-User" in s["name"]), None)
        assert greet_user_symbol is not None, f"Should find Greet-User function in {[s['name'] for s in function_symbols]}"

        # Find references to Greet-User (should be called from Main function at line 91)
        sel_start = greet_user_symbol["selectionRange"]["start"]
        refs = language_server.request_references(main_path, sel_start["line"], sel_start["character"])

        # Should find at least the call site in Main function
        assert refs is not None and len(refs) >= 1, f"Should find references to Greet-User, got {refs}"
        assert any(
            "main.ps1" in ref.get("uri", ref.get("relativePath", "")) for ref in refs
        ), f"Should find reference in main.ps1, got {refs}"

    @pytest.mark.parametrize("language_server", [Language.POWERSHELL], indirect=True)
    def test_powershell_find_definition_across_files(self, language_server: SolidLanguageServer) -> None:
        """Test finding definition of functions across files (main.ps1 -> utils.ps1)."""
        # main.ps1 calls Convert-ToUpperCase from utils.ps1 at line 99 (0-indexed: 98)
        # The call is: $upperName = Convert-ToUpperCase -InputString $User
        # We'll request definition from the call site in main.ps1
        main_path = "main.ps1"

        # Find definition of Convert-ToUpperCase from its usage in main.ps1
        # Line 99 (1-indexed) = line 98 (0-indexed), character position ~16 for "Convert-ToUpperCase"
        definition_locations = language_server.request_definition(main_path, 98, 18)

        # Should find the definition in utils.ps1
        assert (
            definition_locations is not None and len(definition_locations) >= 1
        ), f"Should find definition of Convert-ToUpperCase, got {definition_locations}"
        assert any(
            "utils.ps1" in loc.get("uri", "") for loc in definition_locations
        ), f"Should find definition in utils.ps1, got {definition_locations}"

```

--------------------------------------------------------------------------------
/src/solidlsp/language_servers/clojure_lsp.py:
--------------------------------------------------------------------------------

```python
"""
Provides Clojure specific instantiation of the LanguageServer class. Contains various configurations and settings specific to Clojure.
"""

import logging
import os
import pathlib
import shutil
import subprocess
import threading
from typing import cast

from solidlsp.ls import SolidLanguageServer
from solidlsp.ls_config import LanguageServerConfig
from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams
from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo
from solidlsp.settings import SolidLSPSettings

from .common import RuntimeDependency, RuntimeDependencyCollection

log = logging.getLogger(__name__)


def run_command(cmd: list, capture_output: bool = True) -> subprocess.CompletedProcess:
    return subprocess.run(
        cmd, stdout=subprocess.PIPE if capture_output else None, stderr=subprocess.STDOUT if capture_output else None, text=True, check=True
    )


def verify_clojure_cli() -> None:
    install_msg = "Please install the official Clojure CLI from:\n  https://clojure.org/guides/getting_started"
    if shutil.which("clojure") is None:
        raise FileNotFoundError("`clojure` not found.\n" + install_msg)

    help_proc = run_command(["clojure", "--help"])
    if "-Aaliases" not in help_proc.stdout:
        raise RuntimeError("Detected a Clojure executable, but it does not support '-Aaliases'.\n" + install_msg)

    spath_proc = run_command(["clojure", "-Spath"], capture_output=False)
    if spath_proc.returncode != 0:
        raise RuntimeError("`clojure -Spath` failed; please upgrade to Clojure CLI ≥ 1.10.")


class ClojureLSP(SolidLanguageServer):
    """
    Provides a clojure-lsp specific instantiation of the LanguageServer class. Contains various configurations and settings specific to clojure.
    """

    clojure_lsp_releases = "https://github.com/clojure-lsp/clojure-lsp/releases/latest/download"
    runtime_dependencies = RuntimeDependencyCollection(
        [
            RuntimeDependency(
                id="clojure-lsp",
                url=f"{clojure_lsp_releases}/clojure-lsp-native-macos-aarch64.zip",
                platform_id="osx-arm64",
                archive_type="zip",
                binary_name="clojure-lsp",
            ),
            RuntimeDependency(
                id="clojure-lsp",
                url=f"{clojure_lsp_releases}/clojure-lsp-native-macos-amd64.zip",
                platform_id="osx-x64",
                archive_type="zip",
                binary_name="clojure-lsp",
            ),
            RuntimeDependency(
                id="clojure-lsp",
                url=f"{clojure_lsp_releases}/clojure-lsp-native-linux-aarch64.zip",
                platform_id="linux-arm64",
                archive_type="zip",
                binary_name="clojure-lsp",
            ),
            RuntimeDependency(
                id="clojure-lsp",
                url=f"{clojure_lsp_releases}/clojure-lsp-native-linux-amd64.zip",
                platform_id="linux-x64",
                archive_type="zip",
                binary_name="clojure-lsp",
            ),
            RuntimeDependency(
                id="clojure-lsp",
                url=f"{clojure_lsp_releases}/clojure-lsp-native-windows-amd64.zip",
                platform_id="win-x64",
                archive_type="zip",
                binary_name="clojure-lsp.exe",
            ),
        ]
    )

    def __init__(self, config: LanguageServerConfig, repository_root_path: str, solidlsp_settings: SolidLSPSettings):
        """
        Creates a ClojureLSP instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead.
        """
        clojure_lsp_executable_path = self._setup_runtime_dependencies(config, solidlsp_settings)
        super().__init__(
            config,
            repository_root_path,
            ProcessLaunchInfo(cmd=clojure_lsp_executable_path, cwd=repository_root_path),
            "clojure",
            solidlsp_settings,
        )
        self.server_ready = threading.Event()
        self.initialize_searcher_command_available = threading.Event()
        self.resolve_main_method_available = threading.Event()
        self.service_ready_event = threading.Event()

    @classmethod
    def _setup_runtime_dependencies(cls, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings) -> str:
        """Setup runtime dependencies for clojure-lsp and return the command to start the server."""
        verify_clojure_cli()
        deps = ClojureLSP.runtime_dependencies
        dependency = deps.get_single_dep_for_current_platform()

        clojurelsp_ls_dir = cls.ls_resources_dir(solidlsp_settings)
        clojurelsp_executable_path = deps.binary_path(clojurelsp_ls_dir)
        if not os.path.exists(clojurelsp_executable_path):
            log.info(
                f"Downloading and extracting clojure-lsp from {dependency.url} to {clojurelsp_ls_dir}",
            )
            deps.install(clojurelsp_ls_dir)
        if not os.path.exists(clojurelsp_executable_path):
            raise FileNotFoundError(f"Download failed? Could not find clojure-lsp executable at {clojurelsp_executable_path}")
        os.chmod(clojurelsp_executable_path, 0o755)
        return clojurelsp_executable_path

    @staticmethod
    def _get_initialize_params(repository_absolute_path: str) -> InitializeParams:
        """Returns the init params for clojure-lsp."""
        root_uri = pathlib.Path(repository_absolute_path).as_uri()
        result = {  # type: ignore
            "processId": os.getpid(),
            "rootPath": repository_absolute_path,
            "rootUri": root_uri,
            "capabilities": {
                "workspace": {
                    "applyEdit": True,
                    "workspaceEdit": {"documentChanges": True},
                    "symbol": {"symbolKind": {"valueSet": list(range(1, 27))}},
                    "workspaceFolders": True,
                },
                "textDocument": {
                    "synchronization": {"didSave": True},
                    "publishDiagnostics": {"relatedInformation": True, "tagSupport": {"valueSet": [1, 2]}},
                    "definition": {"linkSupport": True},
                    "references": {},
                    "hover": {"contentFormat": ["markdown", "plaintext"]},
                    "documentSymbol": {
                        "hierarchicalDocumentSymbolSupport": True,
                        "symbolKind": {"valueSet": list(range(1, 27))},  #
                    },
                },
                "general": {"positionEncodings": ["utf-16"]},
            },
            "initializationOptions": {"dependency-scheme": "jar", "text-document-sync-kind": "incremental"},
            "trace": "off",
            "workspaceFolders": [{"uri": root_uri, "name": os.path.basename(repository_absolute_path)}],
        }
        return cast(InitializeParams, result)

    def _start_server(self) -> None:
        def register_capability_handler(params: dict) -> None:
            assert "registrations" in params
            for registration in params["registrations"]:
                if registration["method"] == "workspace/executeCommand":
                    self.initialize_searcher_command_available.set()
                    self.resolve_main_method_available.set()
            return

        def lang_status_handler(params: dict) -> None:
            # TODO: Should we wait for
            # server -> client: {'jsonrpc': '2.0', 'method': 'language/status', 'params': {'type': 'ProjectStatus', 'message': 'OK'}}
            # Before proceeding?
            if params["type"] == "ServiceReady" and params["message"] == "ServiceReady":
                self.service_ready_event.set()

        def execute_client_command_handler(params: dict) -> list:
            return []

        def do_nothing(params: dict) -> None:
            return

        def check_experimental_status(params: dict) -> None:
            if params["quiescent"] is True:
                self.server_ready.set()

        def window_log_message(msg: dict) -> None:
            log.info(f"LSP: window/logMessage: {msg}")

        self.server.on_request("client/registerCapability", register_capability_handler)
        self.server.on_notification("language/status", lang_status_handler)
        self.server.on_notification("window/logMessage", window_log_message)
        self.server.on_request("workspace/executeClientCommand", execute_client_command_handler)
        self.server.on_notification("$/progress", do_nothing)
        self.server.on_notification("textDocument/publishDiagnostics", do_nothing)
        self.server.on_notification("language/actionableNotification", do_nothing)
        self.server.on_notification("experimental/serverStatus", check_experimental_status)

        log.info("Starting clojure-lsp server process")
        self.server.start()

        initialize_params = self._get_initialize_params(self.repository_root_path)

        log.info("Sending initialize request from LSP client to LSP server and awaiting response")
        init_response = self.server.send.initialize(initialize_params)
        assert init_response["capabilities"]["textDocumentSync"]["change"] == 2  # type: ignore
        assert "completionProvider" in init_response["capabilities"]
        # Clojure-lsp completion provider capabilities are more flexible than other servers'
        completion_provider = init_response["capabilities"]["completionProvider"]
        assert completion_provider["resolveProvider"] is True
        assert "triggerCharacters" in completion_provider
        self.server.notify.initialized({})
        # after initialize, Clojure-lsp is ready to serve
        self.server_ready.set()
        self.completions_available.set()

```

--------------------------------------------------------------------------------
/src/solidlsp/language_servers/clangd_language_server.py:
--------------------------------------------------------------------------------

```python
"""
Provides C/C++ specific instantiation of the LanguageServer class. Contains various configurations and settings specific to C/C++.
"""

import logging
import os
import pathlib
import threading
from typing import Any, cast

from solidlsp.ls import SolidLanguageServer
from solidlsp.ls_config import LanguageServerConfig
from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams
from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo
from solidlsp.settings import SolidLSPSettings

from .common import RuntimeDependency, RuntimeDependencyCollection

log = logging.getLogger(__name__)


class ClangdLanguageServer(SolidLanguageServer):
    """
    Provides C/C++ specific instantiation of the LanguageServer class. Contains various configurations and settings specific to C/C++.
    As the project gets bigger in size, building index will take time. Try running clangd multiple times to ensure index is built properly.
    Also make sure compile_commands.json is created at root of the source directory. Check clangd test case for example.
    """

    def __init__(self, config: LanguageServerConfig, repository_root_path: str, solidlsp_settings: SolidLSPSettings):
        """
        Creates a ClangdLanguageServer instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead.
        """
        clangd_executable_path = self._setup_runtime_dependencies(config, solidlsp_settings)
        super().__init__(
            config, repository_root_path, ProcessLaunchInfo(cmd=clangd_executable_path, cwd=repository_root_path), "cpp", solidlsp_settings
        )
        self.server_ready = threading.Event()
        self.service_ready_event = threading.Event()
        self.initialize_searcher_command_available = threading.Event()
        self.resolve_main_method_available = threading.Event()

    @classmethod
    def _setup_runtime_dependencies(cls, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings) -> str:
        """
        Setup runtime dependencies for ClangdLanguageServer and return the command to start the server.
        """
        import shutil

        deps = RuntimeDependencyCollection(
            [
                RuntimeDependency(
                    id="Clangd",
                    description="Clangd for Linux (x64)",
                    url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-linux-19.1.2.zip",
                    platform_id="linux-x64",
                    archive_type="zip",
                    binary_name="clangd_19.1.2/bin/clangd",
                ),
                RuntimeDependency(
                    id="Clangd",
                    description="Clangd for Windows (x64)",
                    url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-windows-19.1.2.zip",
                    platform_id="win-x64",
                    archive_type="zip",
                    binary_name="clangd_19.1.2/bin/clangd.exe",
                ),
                RuntimeDependency(
                    id="Clangd",
                    description="Clangd for macOS (x64)",
                    url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-mac-19.1.2.zip",
                    platform_id="osx-x64",
                    archive_type="zip",
                    binary_name="clangd_19.1.2/bin/clangd",
                ),
                RuntimeDependency(
                    id="Clangd",
                    description="Clangd for macOS (Arm64)",
                    url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-mac-19.1.2.zip",
                    platform_id="osx-arm64",
                    archive_type="zip",
                    binary_name="clangd_19.1.2/bin/clangd",
                ),
            ]
        )

        clangd_ls_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "clangd")

        try:
            dep = deps.get_single_dep_for_current_platform()
        except RuntimeError:
            dep = None

        if dep is None:
            # No prebuilt binary available, look for system-installed clangd
            clangd_executable_path = shutil.which("clangd")
            if not clangd_executable_path:
                raise FileNotFoundError(
                    "Clangd is not installed on your system.\n"
                    + "Please install clangd using your system package manager:\n"
                    + "  Ubuntu/Debian: sudo apt-get install clangd\n"
                    + "  Fedora/RHEL: sudo dnf install clang-tools-extra\n"
                    + "  Arch Linux: sudo pacman -S clang\n"
                    + "See https://clangd.llvm.org/installation for more details."
                )
            log.info(f"Using system-installed clangd at {clangd_executable_path}")
        else:
            # Standard download and install for platforms with prebuilt binaries
            clangd_executable_path = deps.binary_path(clangd_ls_dir)
            if not os.path.exists(clangd_executable_path):
                log.info(f"Clangd executable not found at {clangd_executable_path}. Downloading from {dep.url}")
                _ = deps.install(clangd_ls_dir)
            if not os.path.exists(clangd_executable_path):
                raise FileNotFoundError(
                    f"Clangd executable not found at {clangd_executable_path}.\n"
                    + "Make sure you have installed clangd. See https://clangd.llvm.org/installation"
                )
            os.chmod(clangd_executable_path, 0o755)
        return clangd_executable_path

    @staticmethod
    def _get_initialize_params(repository_absolute_path: str) -> InitializeParams:
        """
        Returns the initialize params for the clangd Language Server.
        """
        root_uri = pathlib.Path(repository_absolute_path).as_uri()
        initialize_params = {
            "locale": "en",
            "capabilities": {
                "textDocument": {
                    "synchronization": {"didSave": True, "dynamicRegistration": True},
                    "completion": {"dynamicRegistration": True, "completionItem": {"snippetSupport": True}},
                    "definition": {"dynamicRegistration": True},
                },
                "workspace": {"workspaceFolders": True, "didChangeConfiguration": {"dynamicRegistration": True}},
            },
            "processId": os.getpid(),
            "rootPath": repository_absolute_path,
            "rootUri": root_uri,
            "workspaceFolders": [
                {
                    "uri": root_uri,
                    "name": "$name",
                }
            ],
        }

        return cast(InitializeParams, initialize_params)

    def _start_server(self) -> None:
        """
        Starts the Clangd Language Server, waits for the server to be ready and yields the LanguageServer instance.

        Usage:
        ```
        async with lsp.start_server():
            # LanguageServer has been initialized and ready to serve requests
            await lsp.request_definition(...)
            await lsp.request_references(...)
            # Shutdown the LanguageServer on exit from scope
        # LanguageServer has been shutdown
        """

        def register_capability_handler(params: Any) -> None:
            assert "registrations" in params
            for registration in params["registrations"]:
                if registration["method"] == "workspace/executeCommand":
                    self.initialize_searcher_command_available.set()
                    self.resolve_main_method_available.set()
            return

        def lang_status_handler(params: Any) -> None:
            # TODO: Should we wait for
            # server -> client: {'jsonrpc': '2.0', 'method': 'language/status', 'params': {'type': 'ProjectStatus', 'message': 'OK'}}
            # Before proceeding?
            if params["type"] == "ServiceReady" and params["message"] == "ServiceReady":
                self.service_ready_event.set()

        def execute_client_command_handler(params: Any) -> list:
            return []

        def do_nothing(params: Any) -> None:
            return

        def check_experimental_status(params: Any) -> None:
            if params["quiescent"] == True:
                self.server_ready.set()

        def window_log_message(msg: dict) -> None:
            log.info(f"LSP: window/logMessage: {msg}")

        self.server.on_request("client/registerCapability", register_capability_handler)
        self.server.on_notification("language/status", lang_status_handler)
        self.server.on_notification("window/logMessage", window_log_message)
        self.server.on_request("workspace/executeClientCommand", execute_client_command_handler)
        self.server.on_notification("$/progress", do_nothing)
        self.server.on_notification("textDocument/publishDiagnostics", do_nothing)
        self.server.on_notification("language/actionableNotification", do_nothing)
        self.server.on_notification("experimental/serverStatus", check_experimental_status)

        log.info("Starting Clangd server process")
        self.server.start()
        initialize_params = self._get_initialize_params(self.repository_root_path)

        log.info("Sending initialize request from LSP client to LSP server and awaiting response")
        init_response = self.server.send.initialize(initialize_params)
        assert init_response["capabilities"]["textDocumentSync"]["change"] == 2  # type: ignore
        assert "completionProvider" in init_response["capabilities"]
        assert init_response["capabilities"]["completionProvider"] == {
            "triggerCharacters": [".", "<", ">", ":", '"', "/", "*"],
            "resolveProvider": False,
        }

        self.server.notify.initialized({})

        self.completions_available.set()
        # set ready flag
        self.server_ready.set()
        self.server_ready.wait()

```

--------------------------------------------------------------------------------
/test/solidlsp/pascal/test_pascal_basic.py:
--------------------------------------------------------------------------------

```python
"""
Basic integration tests for the Pascal language server functionality.

These tests validate the functionality of the language server APIs
like request_document_symbols using the Pascal test repository.

Uses genericptr/pascal-language-server which returns SymbolInformation[] format:
- Returns classes, structs, enums, typedefs, functions/procedures
- Uses correct SymbolKind values: Class=5, Function=12, Method=6, Struct=23
- Method names don't include parent class prefix; uses containerName instead
"""

import pytest

from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language
from solidlsp.ls_types import SymbolKind
from test.conftest import language_tests_enabled

pytestmark = [
    pytest.mark.pascal,
    pytest.mark.skipif(not language_tests_enabled(Language.PASCAL), reason="Pascal tests are disabled (pasls/fpc not available)"),
]


@pytest.mark.pascal
class TestPascalLanguageServerBasics:
    """Test basic functionality of the Pascal language server."""

    @pytest.mark.parametrize("language_server", [Language.PASCAL], indirect=True)
    def test_pascal_language_server_initialization(self, language_server: SolidLanguageServer) -> None:
        """Test that Pascal language server can be initialized successfully."""
        assert language_server is not None
        assert language_server.language == Language.PASCAL

    @pytest.mark.parametrize("language_server", [Language.PASCAL], indirect=True)
    def test_pascal_request_document_symbols(self, language_server: SolidLanguageServer) -> None:
        """Test request_document_symbols for Pascal files.

        genericptr pasls returns proper SymbolKind values:
        - Standalone functions: kind=12 (Function)
        - Classes: kind=5 (Class)
        """
        # Test getting symbols from main.pas
        all_symbols, _root_symbols = language_server.request_document_symbols("main.pas").get_all_symbols_and_roots()

        # Should have symbols
        assert len(all_symbols) > 0, "Should have symbols in main.pas"

        # Should detect standalone functions (SymbolKind.Function = 12)
        function_symbols = [s for s in all_symbols if s.get("kind") == SymbolKind.Function]
        function_names = [s["name"] for s in function_symbols]

        assert "CalculateSum" in function_names, "Should find CalculateSum function"
        assert "PrintMessage" in function_names, "Should find PrintMessage procedure"

        # Should detect classes (SymbolKind.Class = 5)
        class_symbols = [s for s in all_symbols if s.get("kind") == SymbolKind.Class]
        class_names = [s["name"] for s in class_symbols]

        assert "TUser" in class_names, "Should find TUser class"
        assert "TUserManager" in class_names, "Should find TUserManager class"

    @pytest.mark.parametrize("language_server", [Language.PASCAL], indirect=True)
    def test_pascal_class_methods(self, language_server: SolidLanguageServer) -> None:
        """Test detection of class methods in Pascal files.

        pasls returns class methods with SymbolKind.Method (kind 6), not Function (kind 12).
        """
        all_symbols, _root_symbols = language_server.request_document_symbols("main.pas").get_all_symbols_and_roots()

        # Get all method symbols (pasls returns class methods as SymbolKind.Method = 6)
        method_symbols = [s for s in all_symbols if s.get("kind") == SymbolKind.Method]
        method_names = [s["name"] for s in method_symbols]

        # Should detect TUser methods
        expected_tuser_methods = ["Create", "Destroy", "GetInfo", "UpdateAge"]
        for method in expected_tuser_methods:
            found = method in method_names
            assert found, f"Should find method '{method}'"

        # Should detect TUserManager methods
        expected_manager_methods = ["Create", "Destroy", "AddUser", "GetUserCount", "FindUserByName"]
        for method in expected_manager_methods:
            found = method in method_names
            assert found, f"Should find method '{method}'"

    @pytest.mark.parametrize("language_server", [Language.PASCAL], indirect=True)
    def test_pascal_helper_unit_symbols(self, language_server: SolidLanguageServer) -> None:
        """Test function detection in Helper unit."""
        # Test with lib/helper.pas
        helper_all_symbols, _helper_root_symbols = language_server.request_document_symbols("lib/helper.pas").get_all_symbols_and_roots()

        # Should have symbols
        assert len(helper_all_symbols) > 0, "Helper unit should have symbols"

        # Extract function symbols
        function_symbols = [s for s in helper_all_symbols if s.get("kind") == SymbolKind.Function]
        function_names = [s["name"] for s in function_symbols]

        # Should detect standalone functions
        expected_functions = ["GetHelperMessage", "MultiplyNumbers", "LogMessage"]
        for func_name in expected_functions:
            assert func_name in function_names, f"Should find {func_name} function in Helper unit"

        # Should also detect THelper class methods (returned as SymbolKind.Method = 6)
        method_symbols = [s for s in helper_all_symbols if s.get("kind") == SymbolKind.Method]
        method_names = [s["name"] for s in method_symbols]
        assert "FormatString" in method_names, "Should find FormatString method"
        assert "IsEven" in method_names, "Should find IsEven method"

    @pytest.mark.parametrize("language_server", [Language.PASCAL], indirect=True)
    def test_pascal_cross_file_references(self, language_server: SolidLanguageServer) -> None:
        """Test that Pascal LSP can handle cross-file references."""
        # main.pas uses Helper unit
        main_symbols, _main_roots = language_server.request_document_symbols("main.pas").get_all_symbols_and_roots()
        helper_symbols, _helper_roots = language_server.request_document_symbols("lib/helper.pas").get_all_symbols_and_roots()

        # Verify both files have symbols
        assert len(main_symbols) > 0, "main.pas should have symbols"
        assert len(helper_symbols) > 0, "helper.pas should have symbols"

        # Verify GetHelperMessage is in Helper unit
        helper_function_names = [s["name"] for s in helper_symbols if s.get("kind") == SymbolKind.Function]
        assert "GetHelperMessage" in helper_function_names, "Helper unit should export GetHelperMessage"

    @pytest.mark.parametrize("language_server", [Language.PASCAL], indirect=True)
    def test_pascal_symbol_locations(self, language_server: SolidLanguageServer) -> None:
        """Test that symbols have correct location information.

        Note: genericptr pasls returns the interface declaration location (line ~41),
        not the implementation location (line ~115).
        """
        all_symbols, _root_symbols = language_server.request_document_symbols("main.pas").get_all_symbols_and_roots()

        # Find CalculateSum function
        calc_symbols = [s for s in all_symbols if s.get("name") == "CalculateSum"]
        assert len(calc_symbols) > 0, "Should find CalculateSum"

        calc_symbol = calc_symbols[0]

        # Verify it has location information (SymbolInformation format uses location.range)
        if "location" in calc_symbol:
            location = calc_symbol["location"]
            assert "range" in location, "Location should have range"
            assert "start" in location["range"], "Range should have start"
            assert "line" in location["range"]["start"], "Start should have line"
            line = location["range"]["start"]["line"]
        else:
            # DocumentSymbol format uses range directly
            assert "range" in calc_symbol, "Symbol should have range"
            assert "start" in calc_symbol["range"], "Range should have start"
            line = calc_symbol["range"]["start"]["line"]

        # CalculateSum is declared at line 41 in main.pas (0-indexed would be 40)
        # genericptr pasls returns interface declaration location
        assert 35 <= line <= 45, f"CalculateSum should be around line 41 (interface), got {line}"

    @pytest.mark.parametrize("language_server", [Language.PASCAL], indirect=True)
    def test_pascal_namespace_symbol(self, language_server: SolidLanguageServer) -> None:
        """Test that genericptr pasls returns Interface namespace symbol."""
        all_symbols, _root_symbols = language_server.request_document_symbols("main.pas").get_all_symbols_and_roots()

        # genericptr pasls adds an "Interface" namespace symbol
        symbol_names = [s["name"] for s in all_symbols]

        # The Interface section should be represented
        # Note: This depends on pasls configuration
        assert len(all_symbols) > 0, "Should have symbols"
        # Interface namespace may or may not be present depending on pasls configuration
        _ = symbol_names  # used for potential future assertions

    @pytest.mark.parametrize("language_server", [Language.PASCAL], indirect=True)
    def test_pascal_hover_with_doc_comments(self, language_server: SolidLanguageServer) -> None:
        """Test that hover returns documentation comments.

        CalculateSum has /// style doc comments that should appear in hover.
        """
        # CalculateSum is declared at line 46 (1-indexed), so line 45 (0-indexed)
        hover = language_server.request_hover("main.pas", 45, 12)

        assert hover is not None, "Hover should return a result"

        # Extract hover content - handle both dict and object formats
        if isinstance(hover, dict):
            contents = hover.get("contents", {})
            value = contents.get("value", "") if isinstance(contents, dict) else str(contents)
        else:
            value = hover.contents.value if hasattr(hover.contents, "value") else str(hover.contents)

        # Should contain the function signature
        assert "CalculateSum" in value, f"Hover should show function name. Got: {value[:500]}"

        # Should contain the doc comment
        assert "Calculates the sum" in value, f"Hover should include doc comment. Got: {value[:500]}"

```

--------------------------------------------------------------------------------
/src/solidlsp/language_servers/terraform_ls.py:
--------------------------------------------------------------------------------

```python
import logging
import os
import shutil
import threading
from typing import cast

from overrides import override

from solidlsp.ls import SolidLanguageServer
from solidlsp.ls_config import LanguageServerConfig
from solidlsp.ls_utils import PathUtils, PlatformUtils
from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams
from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo
from solidlsp.settings import SolidLSPSettings

from .common import RuntimeDependency, RuntimeDependencyCollection

log = logging.getLogger(__name__)


class TerraformLS(SolidLanguageServer):
    """
    Provides Terraform specific instantiation of the LanguageServer class using terraform-ls.
    """

    @override
    def is_ignored_dirname(self, dirname: str) -> bool:
        return super().is_ignored_dirname(dirname) or dirname in [".terraform", "terraform.tfstate.d"]

    @staticmethod
    def _determine_log_level(line: str) -> int:
        """Classify terraform-ls stderr output to avoid false-positive errors."""
        line_lower = line.lower()

        # File discovery messages that are not actual errors
        if any(
            [
                "discover.go:" in line_lower,
                "walker.go:" in line_lower,
                "walking of {file://" in line_lower,
                "bus: -> discover" in line_lower,
            ]
        ):
            return logging.DEBUG

        # Known informational messages from terraform-ls that contain "error" but aren't errors
        # Note: pattern match is flexible to handle file paths between keywords
        if any(
            [
                "loading module metadata returned error:" in line_lower and "state not changed" in line_lower,
                "incoming notification for" in line_lower,
            ]
        ):
            return logging.DEBUG

        return SolidLanguageServer._determine_log_level(line)

    @staticmethod
    def _ensure_tf_command_available() -> None:
        log.debug("Starting terraform version detection...")

        # 1. Try to find terraform using shutil.which
        terraform_cmd = shutil.which("terraform")
        if terraform_cmd is not None:
            log.debug(f"Found terraform via shutil.which: {terraform_cmd}")
            return

        # TODO: is this needed?
        # 2. Fallback to TERRAFORM_CLI_PATH (set by hashicorp/setup-terraform action)
        if not terraform_cmd:
            terraform_cli_path = os.environ.get("TERRAFORM_CLI_PATH")
            if terraform_cli_path:
                log.debug(f"Trying TERRAFORM_CLI_PATH: {terraform_cli_path}")
                # TODO: use binary name from runtime dependencies if we keep this code
                if os.name == "nt":
                    terraform_binary = os.path.join(terraform_cli_path, "terraform.exe")
                else:
                    terraform_binary = os.path.join(terraform_cli_path, "terraform")
                if os.path.exists(terraform_binary):
                    terraform_cmd = terraform_binary
                    log.debug(f"Found terraform via TERRAFORM_CLI_PATH: {terraform_cmd}")
                    return

        raise RuntimeError(
            "Terraform executable not found, please ensure Terraform is installed."
            "See https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli for instructions."
        )

    @classmethod
    def _setup_runtime_dependencies(cls, solidlsp_settings: SolidLSPSettings) -> str:
        """
        Setup runtime dependencies for terraform-ls.
        Downloads and installs terraform-ls if not already present.
        """
        cls._ensure_tf_command_available()
        platform_id = PlatformUtils.get_platform_id()
        deps = RuntimeDependencyCollection(
            [
                RuntimeDependency(
                    id="TerraformLS",
                    description="terraform-ls for macOS (ARM64)",
                    url="https://releases.hashicorp.com/terraform-ls/0.36.5/terraform-ls_0.36.5_darwin_arm64.zip",
                    platform_id="osx-arm64",
                    archive_type="zip",
                    binary_name="terraform-ls",
                ),
                RuntimeDependency(
                    id="TerraformLS",
                    description="terraform-ls for macOS (x64)",
                    url="https://releases.hashicorp.com/terraform-ls/0.36.5/terraform-ls_0.36.5_darwin_amd64.zip",
                    platform_id="osx-x64",
                    archive_type="zip",
                    binary_name="terraform-ls",
                ),
                RuntimeDependency(
                    id="TerraformLS",
                    description="terraform-ls for Linux (ARM64)",
                    url="https://releases.hashicorp.com/terraform-ls/0.36.5/terraform-ls_0.36.5_linux_arm64.zip",
                    platform_id="linux-arm64",
                    archive_type="zip",
                    binary_name="terraform-ls",
                ),
                RuntimeDependency(
                    id="TerraformLS",
                    description="terraform-ls for Linux (x64)",
                    url="https://releases.hashicorp.com/terraform-ls/0.36.5/terraform-ls_0.36.5_linux_amd64.zip",
                    platform_id="linux-x64",
                    archive_type="zip",
                    binary_name="terraform-ls",
                ),
                RuntimeDependency(
                    id="TerraformLS",
                    description="terraform-ls for Windows (x64)",
                    url="https://releases.hashicorp.com/terraform-ls/0.36.5/terraform-ls_0.36.5_windows_amd64.zip",
                    platform_id="win-x64",
                    archive_type="zip",
                    binary_name="terraform-ls.exe",
                ),
            ]
        )
        dependency = deps.get_single_dep_for_current_platform()

        terraform_ls_executable_path = deps.binary_path(cls.ls_resources_dir(solidlsp_settings))
        if not os.path.exists(terraform_ls_executable_path):
            log.info(f"Downloading terraform-ls from {dependency.url}")
            deps.install(cls.ls_resources_dir(solidlsp_settings))

        assert os.path.exists(terraform_ls_executable_path), f"terraform-ls executable not found at {terraform_ls_executable_path}"

        # Make the executable file executable on Unix-like systems
        if platform_id.value != "win-x64":
            os.chmod(terraform_ls_executable_path, 0o755)

        return terraform_ls_executable_path

    def __init__(self, config: LanguageServerConfig, repository_root_path: str, solidlsp_settings: SolidLSPSettings):
        """
        Creates a TerraformLS instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead.
        """
        terraform_ls_executable_path = self._setup_runtime_dependencies(solidlsp_settings)

        super().__init__(
            config,
            repository_root_path,
            ProcessLaunchInfo(cmd=f"{terraform_ls_executable_path} serve", cwd=repository_root_path),
            "terraform",
            solidlsp_settings,
        )
        self.server_ready = threading.Event()
        self.request_id = 0

    @staticmethod
    def _get_initialize_params(repository_absolute_path: str) -> InitializeParams:
        """
        Returns the initialize params for the Terraform Language Server.
        """
        root_uri = PathUtils.path_to_uri(repository_absolute_path)
        result = {
            "processId": os.getpid(),
            "locale": "en",
            "rootPath": repository_absolute_path,
            "rootUri": root_uri,
            "capabilities": {
                "textDocument": {
                    "synchronization": {"didSave": True, "dynamicRegistration": True},
                    "completion": {"dynamicRegistration": True, "completionItem": {"snippetSupport": True}},
                    "definition": {"dynamicRegistration": True},
                    "documentSymbol": {
                        "dynamicRegistration": True,
                        "hierarchicalDocumentSymbolSupport": True,
                        "symbolKind": {"valueSet": list(range(1, 27))},
                    },
                },
                "workspace": {"workspaceFolders": True, "didChangeConfiguration": {"dynamicRegistration": True}},
            },
            "workspaceFolders": [
                {
                    "name": os.path.basename(repository_absolute_path),
                    "uri": root_uri,
                }
            ],
        }
        return cast(InitializeParams, result)

    def _start_server(self) -> None:
        """Start terraform-ls server process"""

        def register_capability_handler(params: dict) -> None:
            return

        def window_log_message(msg: dict) -> None:
            log.info(f"LSP: window/logMessage: {msg}")

        def do_nothing(params: dict) -> None:
            return

        self.server.on_request("client/registerCapability", register_capability_handler)
        self.server.on_notification("window/logMessage", window_log_message)
        self.server.on_notification("$/progress", do_nothing)
        self.server.on_notification("textDocument/publishDiagnostics", do_nothing)

        log.info("Starting terraform-ls server process")
        self.server.start()
        initialize_params = self._get_initialize_params(self.repository_root_path)

        log.info("Sending initialize request from LSP client to LSP server and awaiting response")
        init_response = self.server.send.initialize(initialize_params)

        # Verify server capabilities
        assert "textDocumentSync" in init_response["capabilities"]
        assert "completionProvider" in init_response["capabilities"]
        assert "definitionProvider" in init_response["capabilities"]

        self.server.notify.initialized({})
        self.completions_available.set()

        # terraform-ls server is typically ready immediately after initialization
        self.server_ready.set()
        self.server_ready.wait()

```

--------------------------------------------------------------------------------
/test/solidlsp/toml/test_toml_symbol_retrieval.py:
--------------------------------------------------------------------------------

```python
"""
Tests for TOML language server symbol retrieval functionality.

These tests focus on advanced symbol operations:
- request_containing_symbol
- request_document_overview
- request_full_symbol_tree
- request_dir_overview
"""

from pathlib import Path

import pytest

from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language

pytestmark = pytest.mark.toml


class TestTomlSymbolRetrieval:
    """Test advanced symbol retrieval functionality for TOML files."""

    @pytest.mark.parametrize("language_server", [Language.TOML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.TOML], indirect=True)
    def test_request_containing_symbol_behavior(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test request_containing_symbol behavior for TOML files.

        Note: Taplo LSP doesn't support definition/containing symbol lookups for TOML files
        since TOML is a configuration format, not code. This test verifies the behavior.
        """
        # Line 2 (0-indexed: 1) is inside the [package] table
        containing_symbol = language_server.request_containing_symbol("Cargo.toml", 1, 5)

        # Taplo doesn't support containing symbol lookup - returns None
        # This is expected behavior for a configuration file format
        assert containing_symbol is None, "TOML LSP doesn't support containing symbol lookup"

    @pytest.mark.parametrize("language_server", [Language.TOML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.TOML], indirect=True)
    def test_request_document_overview_cargo(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test request_document_overview for Cargo.toml."""
        overview = language_server.request_document_overview("Cargo.toml")

        assert overview is not None
        assert len(overview) > 0

        # Get symbol names from overview
        symbol_names = {symbol.get("name") for symbol in overview if "name" in symbol}

        # Verify expected top-level tables appear
        expected_tables = {"package", "dependencies", "dev-dependencies", "features", "workspace"}
        assert expected_tables.issubset(symbol_names), f"Missing expected tables in overview: {expected_tables - symbol_names}"

    @pytest.mark.parametrize("language_server", [Language.TOML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.TOML], indirect=True)
    def test_request_document_overview_pyproject(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test request_document_overview for pyproject.toml."""
        overview = language_server.request_document_overview("pyproject.toml")

        assert overview is not None
        assert len(overview) > 0

        # Get symbol names from overview
        symbol_names = {symbol.get("name") for symbol in overview if "name" in symbol}

        # Verify expected top-level tables appear
        assert "project" in symbol_names, "Should detect 'project' table"
        assert "build-system" in symbol_names, "Should detect 'build-system' table"

    @pytest.mark.parametrize("language_server", [Language.TOML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.TOML], indirect=True)
    def test_request_full_symbol_tree(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test request_full_symbol_tree returns TOML files."""
        symbol_tree = language_server.request_full_symbol_tree()

        assert symbol_tree is not None
        assert len(symbol_tree) > 0

        # The root should be test_repo
        root = symbol_tree[0]
        assert root["name"] == "test_repo"
        assert "children" in root

        # Children should include TOML files
        child_names = {child["name"] for child in root.get("children", [])}
        # Note: File names are stripped of extension in some cases
        assert (
            "Cargo" in child_names or "Cargo.toml" in child_names or any("cargo" in name.lower() for name in child_names)
        ), f"Should find Cargo.toml in tree, got: {child_names}"

    @pytest.mark.parametrize("language_server", [Language.TOML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.TOML], indirect=True)
    def test_request_dir_overview(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test request_dir_overview returns symbols for TOML files."""
        overview = language_server.request_dir_overview(".")

        assert overview is not None
        assert len(overview) > 0

        # Should have entries for both Cargo.toml and pyproject.toml
        file_paths = list(overview.keys())
        assert any("Cargo.toml" in path for path in file_paths), f"Should find Cargo.toml in overview, got: {file_paths}"
        assert any("pyproject.toml" in path for path in file_paths), f"Should find pyproject.toml in overview, got: {file_paths}"

    @pytest.mark.parametrize("language_server", [Language.TOML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.TOML], indirect=True)
    def test_symbol_hierarchy_in_cargo(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test that symbol hierarchy is properly preserved in Cargo.toml."""
        all_symbols, root_symbols = language_server.request_document_symbols("Cargo.toml").get_all_symbols_and_roots()

        # Find the 'package' table
        package_symbol = next((s for s in root_symbols if s.get("name") == "package"), None)
        assert package_symbol is not None, "Should find 'package' as root symbol"

        # Verify it has children (nested keys)
        assert "children" in package_symbol, "'package' should have children"
        child_names = {child.get("name") for child in package_symbol.get("children", [])}

        # Package should have name, version, edition at minimum
        assert "name" in child_names, "'package' should have 'name' child"
        assert "version" in child_names, "'package' should have 'version' child"
        assert "edition" in child_names, "'package' should have 'edition' child"

    @pytest.mark.parametrize("language_server", [Language.TOML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.TOML], indirect=True)
    def test_symbol_hierarchy_in_pyproject(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test that symbol hierarchy is properly preserved in pyproject.toml."""
        all_symbols, root_symbols = language_server.request_document_symbols("pyproject.toml").get_all_symbols_and_roots()

        # Find the 'project' table
        project_symbol = next((s for s in root_symbols if s.get("name") == "project"), None)
        assert project_symbol is not None, "Should find 'project' as root symbol"

        # Verify it has children
        assert "children" in project_symbol, "'project' should have children"
        child_names = {child.get("name") for child in project_symbol.get("children", [])}

        # Project should have name, version, dependencies at minimum
        assert "name" in child_names, "'project' should have 'name' child"
        assert "version" in child_names, "'project' should have 'version' child"

    @pytest.mark.parametrize("language_server", [Language.TOML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.TOML], indirect=True)
    def test_tool_section_hierarchy(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test that tool sections in pyproject.toml are properly structured."""
        all_symbols, root_symbols = language_server.request_document_symbols("pyproject.toml").get_all_symbols_and_roots()

        # Get all symbol names
        all_names = [s.get("name") for s in all_symbols]

        # Should detect tool.ruff, tool.mypy, or tool.pytest
        has_ruff = any("ruff" in name.lower() for name in all_names if name)
        has_mypy = any("mypy" in name.lower() for name in all_names if name)
        has_pytest = any("pytest" in name.lower() for name in all_names if name)

        assert has_ruff or has_mypy or has_pytest, f"Should detect tool sections, got names: {all_names}"

    @pytest.mark.parametrize("language_server", [Language.TOML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.TOML], indirect=True)
    def test_array_of_tables_symbol(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test that [[bin]] array of tables is detected."""
        all_symbols, root_symbols = language_server.request_document_symbols("Cargo.toml").get_all_symbols_and_roots()

        # Get all symbol names
        all_names = [s.get("name") for s in all_symbols]

        # Should detect bin array of tables
        has_bin = "bin" in all_names
        assert has_bin, f"Should detect [[bin]] array of tables, got names: {all_names}"

        # Find the bin symbol and verify its structure
        bin_symbol = next((s for s in all_symbols if s.get("name") == "bin"), None)
        assert bin_symbol is not None, "Should find bin symbol"

        # Array of tables should be kind 18 (array)
        assert bin_symbol.get("kind") == 18, "[[bin]] should have kind 18 (array)"

        # Children of array of tables are indexed by position ('0', '1', etc.)
        if "children" in bin_symbol:
            bin_children = bin_symbol.get("children", [])
            assert len(bin_children) > 0, "[[bin]] should have at least one child element"
            # First child is index '0'
            first_child = bin_children[0]
            assert first_child.get("name") == "0", f"First array element should be named '0', got: {first_child.get('name')}"

            # The '0' element should contain name and path as grandchildren
            if "children" in first_child:
                grandchild_names = {gc.get("name") for gc in first_child.get("children", [])}
                assert "name" in grandchild_names, f"[[bin]] element should have 'name' field, got: {grandchild_names}"
                assert "path" in grandchild_names, f"[[bin]] element should have 'path' field, got: {grandchild_names}"

```

--------------------------------------------------------------------------------
/src/solidlsp/language_servers/zls.py:
--------------------------------------------------------------------------------

```python
"""
Provides Zig specific instantiation of the LanguageServer class using ZLS (Zig Language Server).
"""

import logging
import os
import pathlib
import platform
import shutil
import subprocess
import threading

from overrides import override

from solidlsp.ls import SolidLanguageServer
from solidlsp.ls_config import LanguageServerConfig
from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams
from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo
from solidlsp.settings import SolidLSPSettings

log = logging.getLogger(__name__)


class ZigLanguageServer(SolidLanguageServer):
    """
    Provides Zig specific instantiation of the LanguageServer class using ZLS.
    """

    @override
    def is_ignored_dirname(self, dirname: str) -> bool:
        # For Zig projects, we should ignore:
        # - zig-cache: build cache directory
        # - zig-out: default build output directory
        # - .zig-cache: alternative cache location
        # - node_modules: if the project has JavaScript components
        return super().is_ignored_dirname(dirname) or dirname in ["zig-cache", "zig-out", ".zig-cache", "node_modules", "build", "dist"]

    @staticmethod
    def _get_zig_version() -> str | None:
        """Get the installed Zig version or None if not found."""
        try:
            result = subprocess.run(["zig", "version"], capture_output=True, text=True, check=False)
            if result.returncode == 0:
                return result.stdout.strip()
        except FileNotFoundError:
            return None
        return None

    @staticmethod
    def _get_zls_version() -> str | None:
        """Get the installed ZLS version or None if not found."""
        try:
            result = subprocess.run(["zls", "--version"], capture_output=True, text=True, check=False)
            if result.returncode == 0:
                return result.stdout.strip()
        except FileNotFoundError:
            return None
        return None

    @staticmethod
    def _check_zls_installed() -> bool:
        """Check if ZLS is installed in the system."""
        return shutil.which("zls") is not None

    @staticmethod
    def _setup_runtime_dependency() -> bool:
        """
        Check if required Zig runtime dependencies are available.
        Raises RuntimeError with helpful message if dependencies are missing.
        """
        # Check for Windows and provide error message
        if platform.system() == "Windows":
            raise RuntimeError(
                "Windows is not supported by ZLS in this integration. "
                "Cross-file references don't work reliably on Windows. Reason unknown."
            )

        zig_version = ZigLanguageServer._get_zig_version()
        if not zig_version:
            raise RuntimeError(
                "Zig is not installed. Please install Zig from https://ziglang.org/download/ and make sure it is added to your PATH."
            )

        if not ZigLanguageServer._check_zls_installed():
            zls_version = ZigLanguageServer._get_zls_version()
            if not zls_version:
                raise RuntimeError(
                    "Found Zig but ZLS (Zig Language Server) is not installed.\n"
                    "Please install ZLS from https://github.com/zigtools/zls\n"
                    "You can install it via:\n"
                    "  - Package managers (brew install zls, scoop install zls, etc.)\n"
                    "  - Download pre-built binaries from GitHub releases\n"
                    "  - Build from source with: zig build -Doptimize=ReleaseSafe\n\n"
                    "After installation, make sure 'zls' is added to your PATH."
                )

        return True

    def __init__(self, config: LanguageServerConfig, repository_root_path: str, solidlsp_settings: SolidLSPSettings):
        self._setup_runtime_dependency()

        super().__init__(config, repository_root_path, ProcessLaunchInfo(cmd="zls", cwd=repository_root_path), "zig", solidlsp_settings)
        self.server_ready = threading.Event()
        self.request_id = 0

    @staticmethod
    def _get_initialize_params(repository_absolute_path: str) -> InitializeParams:
        """
        Returns the initialize params for the Zig Language Server.
        """
        root_uri = pathlib.Path(repository_absolute_path).as_uri()
        initialize_params = {
            "locale": "en",
            "capabilities": {
                "textDocument": {
                    "synchronization": {"didSave": True, "dynamicRegistration": True},
                    "definition": {"dynamicRegistration": True},
                    "references": {"dynamicRegistration": True},
                    "documentSymbol": {
                        "dynamicRegistration": True,
                        "hierarchicalDocumentSymbolSupport": True,
                        "symbolKind": {"valueSet": list(range(1, 27))},
                    },
                    "completion": {
                        "dynamicRegistration": True,
                        "completionItem": {
                            "snippetSupport": True,
                            "commitCharactersSupport": True,
                            "documentationFormat": ["markdown", "plaintext"],
                            "deprecatedSupport": True,
                            "preselectSupport": True,
                        },
                    },
                    "hover": {
                        "dynamicRegistration": True,
                        "contentFormat": ["markdown", "plaintext"],
                    },
                },
                "workspace": {
                    "workspaceFolders": True,
                    "didChangeConfiguration": {"dynamicRegistration": True},
                    "configuration": True,
                },
            },
            "processId": os.getpid(),
            "rootPath": repository_absolute_path,
            "rootUri": root_uri,
            "workspaceFolders": [
                {
                    "uri": root_uri,
                    "name": os.path.basename(repository_absolute_path),
                }
            ],
            "initializationOptions": {
                # ZLS specific options based on schema.json
                # Critical paths for ZLS to understand the project
                "zig_exe_path": shutil.which("zig"),  # Path to zig executable
                "zig_lib_path": None,  # Let ZLS auto-detect
                "build_runner_path": None,  # Let ZLS use its built-in runner
                "global_cache_path": None,  # Let ZLS use default cache
                # Build configuration
                "enable_build_on_save": True,  # Enable to analyze project structure
                "build_on_save_args": ["build"],
                # Features
                "enable_snippets": True,
                "enable_argument_placeholders": True,
                "semantic_tokens": "full",
                "warn_style": False,
                "highlight_global_var_declarations": False,
                "skip_std_references": False,
                "prefer_ast_check_as_child_process": True,
                "completion_label_details": True,
                # Inlay hints configuration
                "inlay_hints_show_variable_type_hints": True,
                "inlay_hints_show_struct_literal_field_type": True,
                "inlay_hints_show_parameter_name": True,
                "inlay_hints_show_builtin": True,
                "inlay_hints_exclude_single_argument": True,
                "inlay_hints_hide_redundant_param_names": False,
                "inlay_hints_hide_redundant_param_names_last_token": False,
            },
        }
        return initialize_params  # type: ignore[return-value]

    def _start_server(self) -> None:
        """Start ZLS server process"""

        def register_capability_handler(params: dict) -> None:
            return

        def window_log_message(msg: dict) -> None:
            log.info(f"LSP: window/logMessage: {msg}")

        def do_nothing(params: dict) -> None:
            return

        self.server.on_request("client/registerCapability", register_capability_handler)
        self.server.on_notification("window/logMessage", window_log_message)
        self.server.on_notification("$/progress", do_nothing)
        self.server.on_notification("textDocument/publishDiagnostics", do_nothing)

        log.info("Starting ZLS server process")
        self.server.start()
        initialize_params = self._get_initialize_params(self.repository_root_path)

        log.info("Sending initialize request from LSP client to LSP server and awaiting response")
        init_response = self.server.send.initialize(initialize_params)

        # Verify server capabilities
        assert "textDocumentSync" in init_response["capabilities"]
        assert "definitionProvider" in init_response["capabilities"]
        assert "documentSymbolProvider" in init_response["capabilities"]
        assert "referencesProvider" in init_response["capabilities"]

        self.server.notify.initialized({})
        self.completions_available.set()

        # ZLS server is ready after initialization
        self.server_ready.set()
        self.server_ready.wait()

        # Open build.zig if it exists to help ZLS understand project structure
        build_zig_path = os.path.join(self.repository_root_path, "build.zig")
        if os.path.exists(build_zig_path):
            try:
                with open(build_zig_path, encoding="utf-8") as f:
                    content = f.read()
                    uri = pathlib.Path(build_zig_path).as_uri()
                    self.server.notify.did_open_text_document(
                        {
                            "textDocument": {
                                "uri": uri,
                                "languageId": "zig",
                                "version": 1,
                                "text": content,
                            }
                        }
                    )
                    log.info("Opened build.zig to provide project context to ZLS")
            except Exception as e:
                log.warning(f"Failed to open build.zig: {e}")

```

--------------------------------------------------------------------------------
/test/solidlsp/yaml_ls/test_yaml_basic.py:
--------------------------------------------------------------------------------

```python
"""
Basic integration tests for the YAML language server functionality.

These tests validate the functionality of the language server APIs
like request_document_symbols using the YAML test repository.
"""

from pathlib import Path

import pytest

from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language


@pytest.mark.yaml
class TestYAMLLanguageServerBasics:
    """Test basic functionality of the YAML language server."""

    @pytest.mark.parametrize("language_server", [Language.YAML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.YAML], indirect=True)
    def test_yaml_language_server_initialization(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test that YAML language server can be initialized successfully."""
        assert language_server is not None
        assert language_server.language == Language.YAML
        assert language_server.is_running()
        assert Path(language_server.language_server.repository_root_path).resolve() == repo_path.resolve()

    @pytest.mark.parametrize("language_server", [Language.YAML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.YAML], indirect=True)
    def test_yaml_config_file_symbols(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test document symbols detection in config.yaml with specific symbol verification."""
        all_symbols, root_symbols = language_server.request_document_symbols("config.yaml").get_all_symbols_and_roots()

        assert all_symbols is not None, "Should return symbols for config.yaml"
        assert len(all_symbols) > 0, f"Should find symbols in config.yaml, found {len(all_symbols)}"

        # Verify specific top-level keys are detected
        symbol_names = [sym.get("name") for sym in all_symbols]
        assert "app" in symbol_names, "Should detect 'app' key in config.yaml"
        assert "database" in symbol_names, "Should detect 'database' key in config.yaml"
        assert "logging" in symbol_names, "Should detect 'logging' key in config.yaml"
        assert "features" in symbol_names, "Should detect 'features' key in config.yaml"

        # Verify nested symbols exist (child keys under 'app')
        assert "name" in symbol_names, "Should detect nested 'name' key"
        assert "port" in symbol_names, "Should detect nested 'port' key"
        assert "debug" in symbol_names, "Should detect nested 'debug' key"

        # Check symbol kinds are appropriate (LSP kinds: 2=module/namespace, 15=string, 16=number, 17=boolean)
        app_symbol = next((s for s in all_symbols if s.get("name") == "app"), None)
        assert app_symbol is not None, "Should find 'app' symbol"
        assert app_symbol.get("kind") == 2, "Top-level object should have kind 2 (module/namespace)"

        port_symbol = next((s for s in all_symbols if s.get("name") == "port"), None)
        assert port_symbol is not None, "Should find 'port' symbol"
        assert port_symbol.get("kind") == 16, "'port' should have kind 16 (number)"

        debug_symbol = next((s for s in all_symbols if s.get("name") == "debug"), None)
        assert debug_symbol is not None, "Should find 'debug' symbol"
        assert debug_symbol.get("kind") == 17, "'debug' should have kind 17 (boolean)"

    @pytest.mark.parametrize("language_server", [Language.YAML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.YAML], indirect=True)
    def test_yaml_services_file_symbols(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test symbol detection in services.yml Docker Compose file."""
        all_symbols, root_symbols = language_server.request_document_symbols("services.yml").get_all_symbols_and_roots()

        assert all_symbols is not None, "Should return symbols for services.yml"
        assert len(all_symbols) > 0, f"Should find symbols in services.yml, found {len(all_symbols)}"

        # Verify specific top-level keys from Docker Compose file
        symbol_names = [sym.get("name") for sym in all_symbols]
        assert "version" in symbol_names, "Should detect 'version' key"
        assert "services" in symbol_names, "Should detect 'services' key"
        assert "networks" in symbol_names, "Should detect 'networks' key"
        assert "volumes" in symbol_names, "Should detect 'volumes' key"

        # Verify service names
        assert "web" in symbol_names, "Should detect 'web' service"
        assert "api" in symbol_names, "Should detect 'api' service"
        assert "database" in symbol_names, "Should detect 'database' service"

        # Check that arrays are properly detected
        ports_symbols = [s for s in all_symbols if s.get("name") == "ports"]
        assert len(ports_symbols) > 0, "Should find 'ports' arrays in services"
        # Arrays should have kind 18
        for ports_sym in ports_symbols:
            assert ports_sym.get("kind") == 18, "'ports' should have kind 18 (array)"

    @pytest.mark.parametrize("language_server", [Language.YAML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.YAML], indirect=True)
    def test_yaml_data_file_symbols(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test symbol detection in data.yaml file with array structures."""
        all_symbols, root_symbols = language_server.request_document_symbols("data.yaml").get_all_symbols_and_roots()

        assert all_symbols is not None, "Should return symbols for data.yaml"
        assert len(all_symbols) > 0, f"Should find symbols in data.yaml, found {len(all_symbols)}"

        # Verify top-level keys
        symbol_names = [sym.get("name") for sym in all_symbols]
        assert "users" in symbol_names, "Should detect 'users' array"
        assert "projects" in symbol_names, "Should detect 'projects' array"

        # Verify array elements (indexed by position)
        # data.yaml has user entries and project entries
        assert "id" in symbol_names, "Should detect 'id' fields in array elements"
        assert "name" in symbol_names, "Should detect 'name' fields"
        assert "email" in symbol_names, "Should detect 'email' fields"
        assert "roles" in symbol_names, "Should detect 'roles' arrays"

    @pytest.mark.parametrize("language_server", [Language.YAML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.YAML], indirect=True)
    def test_yaml_symbols_with_body(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test request_document_symbols with body extraction."""
        all_symbols, root_symbols = language_server.request_document_symbols("config.yaml").get_all_symbols_and_roots()

        assert all_symbols is not None, "Should return symbols for config.yaml"
        assert len(all_symbols) > 0, "Should have symbols"

        # Find the 'app' symbol and verify its body
        app_symbol = next((s for s in all_symbols if s.get("name") == "app"), None)
        assert app_symbol is not None, "Should find 'app' symbol"

        # Check that body exists and contains expected content
        assert "body" in app_symbol, "'app' symbol should have body"
        app_body = app_symbol["body"]
        assert "app:" in app_body, "Body should start with 'app:'"
        assert "name: test-application" in app_body, "Body should contain 'name' field"
        assert "version: 1.0.0" in app_body, "Body should contain 'version' field"
        assert "port: 8080" in app_body, "Body should contain 'port' field"
        assert "debug: true" in app_body, "Body should contain 'debug' field"

        # Find a simple string value symbol and verify its body
        name_symbols = [s for s in all_symbols if s.get("name") == "name" and "body" in s]
        assert len(name_symbols) > 0, "Should find 'name' symbols with bodies"
        # At least one should contain "test-application"
        assert any("test-application" in s["body"] for s in name_symbols), "Should find name with test-application"

        # Find the database symbol and check its body
        database_symbol = next((s for s in all_symbols if s.get("name") == "database"), None)
        assert database_symbol is not None, "Should find 'database' symbol"
        assert "body" in database_symbol, "'database' symbol should have body"
        db_body = database_symbol["body"]
        assert "database:" in db_body, "Body should start with 'database:'"
        assert "host: localhost" in db_body, "Body should contain host configuration"
        assert "port: 5432" in db_body, "Body should contain port configuration"

    @pytest.mark.parametrize("language_server", [Language.YAML], indirect=True)
    @pytest.mark.parametrize("repo_path", [Language.YAML], indirect=True)
    def test_yaml_symbol_ranges(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
        """Test that symbols have proper range information."""
        all_symbols, root_symbols = language_server.request_document_symbols("config.yaml").get_all_symbols_and_roots()

        assert all_symbols is not None
        assert len(all_symbols) > 0

        # Check the 'app' symbol range
        app_symbol = next((s for s in all_symbols if s.get("name") == "app"), None)
        assert app_symbol is not None, "Should find 'app' symbol"
        assert "range" in app_symbol, "'app' symbol should have range"

        app_range = app_symbol["range"]
        assert "start" in app_range, "Range should have start"
        assert "end" in app_range, "Range should have end"
        assert app_range["start"]["line"] == 1, "'app' should start at line 1 (0-indexed, actual line 2)"
        # The app block spans from line 2 to line 7 in the file (1-indexed)
        # In 0-indexed LSP coordinates: line 1 (start) to line 6 (end)
        assert app_range["end"]["line"] == 6, "'app' should end at line 6 (0-indexed)"

        # Check a nested symbol range
        port_symbols = [s for s in all_symbols if s.get("name") == "port"]
        assert len(port_symbols) > 0, "Should find 'port' symbols"
        # Find the one under 'app' (should be at line 4 in 0-indexed, actual line 5)
        app_port = next((s for s in port_symbols if s["range"]["start"]["line"] == 4), None)
        assert app_port is not None, "Should find 'port' under 'app'"
        assert app_port["range"]["start"]["character"] == 2, "'port' should be indented 2 spaces"

```

--------------------------------------------------------------------------------
/test/solidlsp/haskell/test_haskell_basic.py:
--------------------------------------------------------------------------------

```python
"""
Rigorous tests for Haskell Language Server integration with Serena.

Tests prove that Serena's symbol tools can:
1. Discover all expected symbols with precise matching
2. Track cross-file references accurately
3. Identify data type structures and record fields
4. Navigate between definitions and usages

Test Repository Structure:
- src/Calculator.hs: Calculator data type, arithmetic functions (add, subtract, multiply, divide, calculate)
- src/Helper.hs: Helper functions (validateNumber, isPositive, isNegative, absolute)
- app/Main.hs: Main entry point using Calculator and Helper modules
"""

import sys

import pytest

from solidlsp.ls import SolidLanguageServer
from solidlsp.ls_config import Language


@pytest.mark.haskell
@pytest.mark.skipif(sys.platform == "win32", reason="HLS not installed on Windows CI")
class TestHaskellLanguageServer:
    @pytest.mark.parametrize("language_server", [Language.HASKELL], indirect=True)
    def test_calculator_module_symbols(self, language_server: SolidLanguageServer):
        """
        Test precise symbol discovery in Calculator.hs.

        Verifies that Serena can identify:
        - Data type definition (Calculator with record fields)
        - All exported functions with correct names
        - Module structure
        """
        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
        expected_symbols = {
            "Calculator",  # Data type
            "add",  # Function: Int -> Int -> Int
            "subtract",  # Function: Int -> Int -> Int
            "multiply",  # Function: Int -> Int -> Int
            "divide",  # Function: Int -> Int -> Maybe Int
            "calculate",  # Function: Calculator -> String -> Int -> Int -> Maybe Int
        }

        # Verify all expected symbols are present
        missing = expected_symbols - symbol_names
        assert not missing, f"Missing expected symbols in Calculator.hs: {missing}"

        # Verify Calculator data type exists
        calculator_symbol = next((s for s in all_symbols if s["name"] == "Calculator"), None)
        assert calculator_symbol is not None, "Calculator data type not found"

        # The Calculator should be identified as a data type
        # HLS may use different SymbolKind values (1=File, 5=Class, 23=Struct)
        assert calculator_symbol["kind"] in [
            1,
            5,
            23,
        ], f"Calculator should be a data type (kind 1, 5, or 23), got kind {calculator_symbol['kind']}"

    @pytest.mark.parametrize("language_server", [Language.HASKELL], indirect=True)
    def test_helper_module_symbols(self, language_server: SolidLanguageServer):
        """
        Test precise symbol discovery in Helper.hs.

        Verifies Serena identifies all helper functions that are imported
        and used by Calculator module.
        """
        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)
        expected_symbols = {
            "validateNumber",  # Function used by Calculator.add and Calculator.subtract
            "isPositive",  # Predicate function
            "isNegative",  # Predicate function used by absolute
            "absolute",  # Function that uses isNegative
        }

        # All expected symbols should be present (module name is optional)
        missing = expected_symbols - symbol_names
        assert not missing, f"Missing expected symbols in Helper.hs: {missing}"

        # Verify no unexpected symbols beyond the module name
        extra = symbol_names - expected_symbols - {"Helper"}
        assert not extra, f"Unexpected symbols in Helper.hs: {extra}"

    @pytest.mark.parametrize("language_server", [Language.HASKELL], indirect=True)
    def test_main_module_imports(self, language_server: SolidLanguageServer):
        """
        Test that Main.hs properly references both Calculator and Helper modules.

        Verifies Serena can identify cross-module dependencies.
        """
        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
        assert "main" in symbol_names, "Main.hs should contain 'main' function"

    @pytest.mark.parametrize("language_server", [Language.HASKELL], indirect=True)
    def test_cross_file_references_validateNumber(self, language_server: SolidLanguageServer):
        """
        Test cross-file reference tracking for validateNumber function.

        validateNumber is defined in Helper.hs:9 and used in:
        - Calculator.hs:21 (in add function)
        - Calculator.hs:25 (in subtract function)

        This proves Serena can track function usage across module boundaries.
        """
        # Get references to validateNumber (defined at line 9, 0-indexed = line 8)
        references = language_server.request_references("src/Helper.hs", line=8, column=0)

        # Should find at least: definition in Helper.hs + 2 usages in Calculator.hs
        assert len(references) >= 2, f"Expected at least 2 references to validateNumber (used in add and subtract), got {len(references)}"

        # Verify we have references in Calculator.hs
        reference_paths = [ref["relativePath"] for ref in references]
        calculator_refs = [path for path in reference_paths if "Calculator.hs" in path]

        assert len(calculator_refs) >= 2, (
            f"Expected at least 2 references in Calculator.hs (add and subtract functions), "
            f"got {len(calculator_refs)} references in Calculator.hs"
        )

    @pytest.mark.parametrize("language_server", [Language.HASKELL], indirect=True)
    def test_within_file_references_isNegative(self, language_server: SolidLanguageServer):
        """
        Test within-file reference tracking for isNegative function.

        isNegative is defined in Helper.hs:17 and used in Helper.hs:22 (absolute function).
        This proves Serena can track intra-module function calls.
        """
        # isNegative defined at line 17 (0-indexed = line 16)
        references = language_server.request_references("src/Helper.hs", line=16, column=0)

        # Should find: definition + usage in absolute function
        assert len(references) >= 1, f"Expected at least 1 reference to isNegative (used in absolute), got {len(references)}"

        # All references should be in Helper.hs
        reference_paths = [ref["relativePath"] for ref in references]
        assert all(
            "Helper.hs" in path for path in reference_paths
        ), f"All isNegative references should be in Helper.hs, got: {reference_paths}"

    @pytest.mark.parametrize("language_server", [Language.HASKELL], indirect=True)
    def test_function_references_from_main(self, language_server: SolidLanguageServer):
        """
        Test that functions used in Main.hs can be traced back to their definitions.

        Main.hs:12 calls 'add' from Calculator module.
        Main.hs:25 calls 'isPositive' from Helper module.
        Main.hs:26 calls 'absolute' from Helper module.

        This proves Serena can track cross-module function calls from executable code.
        """
        # Test 'add' function references (defined in Calculator.hs:20, 0-indexed = line 19)
        add_refs = language_server.request_references("src/Calculator.hs", line=19, column=0)

        # Should find references in Main.hs and possibly Calculator.hs (calculate function uses it)
        assert len(add_refs) >= 1, f"Expected at least 1 reference to 'add', got {len(add_refs)}"

        add_ref_paths = [ref["relativePath"] for ref in add_refs]
        # Should have at least one reference in Main.hs or Calculator.hs
        assert any(
            "Main.hs" in path or "Calculator.hs" in path for path in add_ref_paths
        ), f"Expected 'add' to be referenced in Main.hs or Calculator.hs, got: {add_ref_paths}"

    @pytest.mark.parametrize("language_server", [Language.HASKELL], indirect=True)
    def test_multiply_function_usage_in_calculate(self, language_server: SolidLanguageServer):
        """
        Test that multiply function usage is tracked within Calculator module.

        multiply is defined in Calculator.hs:28 and used in:
        - Calculator.hs:41 (in calculate function via pattern matching)
        - Main.hs:20 (via calculate call with "multiply" operator)

        This proves Serena can track function references even when called indirectly.
        """
        # multiply defined at line 28 (0-indexed = line 27)
        multiply_refs = language_server.request_references("src/Calculator.hs", line=27, column=0)

        # Should find at least the usage in calculate function
        assert len(multiply_refs) >= 1, f"Expected at least 1 reference to 'multiply', got {len(multiply_refs)}"

        # Should have reference in Calculator.hs (calculate function)
        multiply_ref_paths = [ref["relativePath"] for ref in multiply_refs]
        assert any(
            "Calculator.hs" in path for path in multiply_ref_paths
        ), f"Expected 'multiply' to be referenced in Calculator.hs, got: {multiply_ref_paths}"

    @pytest.mark.parametrize("language_server", [Language.HASKELL], indirect=True)
    def test_data_type_constructor_references(self, language_server: SolidLanguageServer):
        """
        Test that Calculator data type constructor usage is tracked.

        Calculator is defined in Calculator.hs:14 and used in:
        - Main.hs:8 (constructor call: Calculator "TestCalc" 1)
        - Calculator.hs:37 (type signature for calculate function)

        This proves Serena can track data type constructor references.
        """
        # Calculator data type defined at line 14 (0-indexed = line 13)
        calculator_refs = language_server.request_references("src/Calculator.hs", line=13, column=5)

        # Should find usage in Main.hs
        assert len(calculator_refs) >= 1, f"Expected at least 1 reference to Calculator constructor, got {len(calculator_refs)}"

        # Should have at least one reference in Main.hs or Calculator.hs
        calc_ref_paths = [ref["relativePath"] for ref in calculator_refs]
        assert any(
            "Main.hs" in path or "Calculator.hs" in path for path in calc_ref_paths
        ), f"Expected Calculator to be referenced in Main.hs or Calculator.hs, got: {calc_ref_paths}"

```

--------------------------------------------------------------------------------
/test/solidlsp/erlang/test_erlang_ignored_dirs.py:
--------------------------------------------------------------------------------

```python
from collections.abc import Generator
from pathlib import Path

import pytest

from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language
from test.conftest import start_ls_context

from . import ERLANG_LS_UNAVAILABLE, ERLANG_LS_UNAVAILABLE_REASON

# These marks will be applied to all tests in this module
pytestmark = [
    pytest.mark.erlang,
    pytest.mark.skipif(ERLANG_LS_UNAVAILABLE, reason=f"Erlang LS not available: {ERLANG_LS_UNAVAILABLE_REASON}"),
]


@pytest.fixture(scope="module")
def ls_with_ignored_dirs() -> Generator[SolidLanguageServer, None, None]:
    """Fixture to set up an LS for the erlang test repo with the 'ignored_dir' directory ignored."""
    ignored_paths = ["_build", "ignored_dir"]
    with start_ls_context(language=Language.ERLANG, ignored_paths=ignored_paths) as ls:
        yield ls


@pytest.mark.timeout(60)  # Add 60 second timeout
@pytest.mark.xfail(reason="Known timeout issue on Ubuntu CI with Erlang LS server startup", strict=False)
@pytest.mark.parametrize("ls_with_ignored_dirs", [Language.ERLANG], indirect=True)
def test_symbol_tree_ignores_dir(ls_with_ignored_dirs: SolidLanguageServer):
    """Tests that request_full_symbol_tree ignores the configured directory."""
    root = ls_with_ignored_dirs.request_full_symbol_tree()[0]
    root_children = root["children"]
    children_names = {child["name"] for child in root_children}

    # Should have src, include, and test directories, but not _build or ignored_dir
    expected_dirs = {"src", "include", "test"}
    found_expected = expected_dirs.intersection(children_names)
    assert len(found_expected) > 0, f"Expected some dirs from {expected_dirs} to be in {children_names}"
    assert "_build" not in children_names, f"_build should not be in {children_names}"
    assert "ignored_dir" not in children_names, f"ignored_dir should not be in {children_names}"


@pytest.mark.timeout(60)  # Add 60 second timeout
@pytest.mark.xfail(reason="Known timeout issue on Ubuntu CI with Erlang LS server startup", strict=False)
@pytest.mark.parametrize("ls_with_ignored_dirs", [Language.ERLANG], indirect=True)
def test_find_references_ignores_dir(ls_with_ignored_dirs: SolidLanguageServer):
    """Tests that find_references ignores the configured directory."""
    # Location of user record, which might be referenced in ignored_dir
    definition_file = "include/records.hrl"

    # Find the user record definition
    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)
        if user_symbol:
            break

    if not user_symbol or "selectionRange" not in user_symbol:
        pytest.skip("User record symbol not found for reference testing")

    sel_start = user_symbol["selectionRange"]["start"]
    references = ls_with_ignored_dirs.request_references(definition_file, sel_start["line"], sel_start["character"])

    # Assert that _build and ignored_dir do not appear in the references
    assert not any("_build" in ref["relativePath"] for ref in references), "_build should be ignored"
    assert not any("ignored_dir" in ref["relativePath"] for ref in references), "ignored_dir should be ignored"


@pytest.mark.timeout(60)  # Add 60 second timeout
@pytest.mark.xfail(reason="Known timeout issue on Ubuntu CI with Erlang LS server startup", strict=False)
@pytest.mark.parametrize("repo_path", [Language.ERLANG], indirect=True)
def test_refs_and_symbols_with_glob_patterns(repo_path: Path) -> None:
    """Tests that refs and symbols with glob patterns are ignored."""
    ignored_paths = ["_build*", "ignored_*", "*.tmp"]
    with start_ls_context(language=Language.ERLANG, repo_path=str(repo_path), ignored_paths=ignored_paths) as ls:
        # Same as in the above tests
        root = ls.request_full_symbol_tree()[0]
        root_children = root["children"]
        children_names = {child["name"] for child in root_children}

        # Should have src, include, and test directories, but not _build or ignored_dir
        expected_dirs = {"src", "include", "test"}
        found_expected = expected_dirs.intersection(children_names)
        assert len(found_expected) > 0, f"Expected some dirs from {expected_dirs} to be in {children_names}"
        assert "_build" not in children_names, f"_build should not be in {children_names} (glob pattern)"
        assert "ignored_dir" not in children_names, f"ignored_dir should not be in {children_names} (glob pattern)"

        # Test that the refs and symbols with glob patterns are ignored
        definition_file = "include/records.hrl"

        # Find the user record definition
        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)
            if user_symbol:
                break

        if user_symbol and "selectionRange" in user_symbol:
            sel_start = user_symbol["selectionRange"]["start"]
            references = ls.request_references(definition_file, sel_start["line"], sel_start["character"])

            # Assert that _build and ignored_dir do not appear in references
            assert not any("_build" in ref["relativePath"] for ref in references), "_build should be ignored (glob)"
            assert not any("ignored_dir" in ref["relativePath"] for ref in references), "ignored_dir should be ignored (glob)"


@pytest.mark.parametrize("language_server", [Language.ERLANG], indirect=True)
def test_default_ignored_directories(language_server: SolidLanguageServer):
    """Test that default Erlang directories are ignored."""
    # Test that Erlang-specific directories are ignored by default
    assert language_server.is_ignored_dirname("_build"), "_build should be ignored"
    assert language_server.is_ignored_dirname("ebin"), "ebin should be ignored"
    assert language_server.is_ignored_dirname("deps"), "deps should be ignored"
    assert language_server.is_ignored_dirname(".rebar3"), ".rebar3 should be ignored"
    assert language_server.is_ignored_dirname("_checkouts"), "_checkouts should be ignored"
    assert language_server.is_ignored_dirname("node_modules"), "node_modules should be ignored"

    # Test that important directories are not ignored
    assert not language_server.is_ignored_dirname("src"), "src should not be ignored"
    assert not language_server.is_ignored_dirname("include"), "include should not be ignored"
    assert not language_server.is_ignored_dirname("test"), "test should not be ignored"
    assert not language_server.is_ignored_dirname("priv"), "priv should not be ignored"


@pytest.mark.parametrize("language_server", [Language.ERLANG], indirect=True)
def test_symbol_tree_excludes_build_dirs(language_server: SolidLanguageServer):
    """Test that symbol tree excludes build and dependency directories."""
    symbol_tree = language_server.request_full_symbol_tree()

    if symbol_tree:
        root = symbol_tree[0]
        children_names = {child["name"] for child in root.get("children", [])}

        # Build and dependency directories should not appear
        ignored_dirs = {"_build", "ebin", "deps", ".rebar3", "_checkouts", "node_modules"}
        found_ignored = ignored_dirs.intersection(children_names)
        assert len(found_ignored) == 0, f"Found ignored directories in symbol tree: {found_ignored}"

        # Important directories should appear
        important_dirs = {"src", "include", "test"}
        found_important = important_dirs.intersection(children_names)
        assert len(found_important) > 0, f"Expected to find important directories: {important_dirs}, got: {children_names}"


@pytest.mark.parametrize("language_server", [Language.ERLANG], indirect=True)
def test_ignore_compiled_files(language_server: SolidLanguageServer):
    """Test that compiled Erlang files are ignored."""
    # Test that beam files are ignored
    assert language_server.is_ignored_filename("module.beam"), "BEAM files should be ignored"
    assert language_server.is_ignored_filename("app.beam"), "BEAM files should be ignored"

    # Test that source files are not ignored
    assert not language_server.is_ignored_filename("module.erl"), "Erlang source files should not be ignored"
    assert not language_server.is_ignored_filename("records.hrl"), "Header files should not be ignored"


@pytest.mark.parametrize("language_server", [Language.ERLANG], indirect=True)
def test_rebar_directories_ignored(language_server: SolidLanguageServer):
    """Test that rebar-specific directories are ignored."""
    # Test rebar3-specific directories
    assert language_server.is_ignored_dirname("_build"), "rebar3 _build should be ignored"
    assert language_server.is_ignored_dirname("_checkouts"), "rebar3 _checkouts should be ignored"
    assert language_server.is_ignored_dirname(".rebar3"), "rebar3 cache should be ignored"

    # Test that rebar.lock and rebar.config are not ignored (they are configuration files)
    assert not language_server.is_ignored_filename("rebar.config"), "rebar.config should not be ignored"
    assert not language_server.is_ignored_filename("rebar.lock"), "rebar.lock should not be ignored"


@pytest.mark.parametrize("ls_with_ignored_dirs", [Language.ERLANG], indirect=True)
def test_document_symbols_ignores_dirs(ls_with_ignored_dirs: SolidLanguageServer):
    """Test that document symbols from ignored directories are not included."""
    # 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).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"
    except Exception:
        # This is expected - the file should not be accessible
        pass


@pytest.mark.parametrize("language_server", [Language.ERLANG], indirect=True)
def test_erlang_specific_ignore_patterns(language_server: SolidLanguageServer):
    """Test Erlang-specific ignore patterns work correctly."""
    erlang_ignored_dirs = ["_build", "ebin", ".rebar3", "_checkouts", "cover"]

    # These should be ignored
    for dirname in erlang_ignored_dirs:
        assert language_server.is_ignored_dirname(dirname), f"{dirname} should be ignored"

    # These should not be ignored
    erlang_important_dirs = ["src", "include", "test", "priv"]
    for dirname in erlang_important_dirs:
        assert not language_server.is_ignored_dirname(dirname), f"{dirname} should not be ignored"

```

--------------------------------------------------------------------------------
/src/serena/config/context_mode.py:
--------------------------------------------------------------------------------

```python
"""
Context and Mode configuration loader
"""

import os
from dataclasses import dataclass, field
from pathlib import Path
from typing import TYPE_CHECKING, Self

import yaml
from sensai.util import logging
from sensai.util.string import ToStringMixin

from serena.config.serena_config import SerenaPaths, ToolInclusionDefinition
from serena.constants import (
    DEFAULT_CONTEXT,
    DEFAULT_MODES,
    INTERNAL_MODE_YAMLS_DIR,
    SERENA_FILE_ENCODING,
    SERENAS_OWN_CONTEXT_YAMLS_DIR,
    SERENAS_OWN_MODE_YAMLS_DIR,
)

if TYPE_CHECKING:
    pass

log = logging.getLogger(__name__)


@dataclass(kw_only=True)
class SerenaAgentMode(ToolInclusionDefinition, ToStringMixin):
    """Represents a mode of operation for the agent, typically read off a YAML file.
    An agent can be in multiple modes simultaneously as long as they are not mutually exclusive.
    The modes can be adjusted after the agent is running, for example for switching from planning to editing.
    """

    name: str
    prompt: str
    """
    a Jinja2 template for the generation of the system prompt.
    It is formatted by the agent (see SerenaAgent._format_prompt()).
    """
    description: str = ""
    _yaml_path: Path | None = field(default=None, repr=False, compare=False)
    """
    Internal field storing the path to the YAML file this mode was loaded from.
    Used to support loading modes from arbitrary file paths.
    """

    def _tostring_includes(self) -> list[str]:
        return ["name"]

    def print_overview(self) -> None:
        """Print an overview of the mode."""
        print(f"{self.name}:\n {self.description}")
        if self.excluded_tools:
            print(" excluded tools:\n  " + ", ".join(sorted(self.excluded_tools)))

    @classmethod
    def from_yaml(cls, yaml_path: str | Path) -> Self:
        """Load a mode from a YAML file."""
        yaml_as_path = Path(yaml_path).resolve()
        with Path(yaml_as_path).open(encoding=SERENA_FILE_ENCODING) as f:
            data = yaml.safe_load(f)
        name = data.pop("name", yaml_as_path.stem)
        return cls(name=name, _yaml_path=yaml_as_path, **data)

    @classmethod
    def get_path(cls, name: str, instance: Self | None = None) -> str:
        """Get the path to the YAML file for a mode.

        :param name: The name of the mode
        :param instance: Optional mode instance. If provided and it has a stored path, that path is returned.
        :return: The path to the mode's YAML file
        """
        # If we have an instance with a stored path, use that
        if instance is not None and instance._yaml_path is not None:
            return str(instance._yaml_path)

        fname = f"{name}.yml"
        custom_mode_path = os.path.join(SerenaPaths().user_modes_dir, fname)
        if os.path.exists(custom_mode_path):
            return custom_mode_path

        own_yaml_path = os.path.join(SERENAS_OWN_MODE_YAMLS_DIR, fname)
        if not os.path.exists(own_yaml_path):
            raise FileNotFoundError(
                f"Mode {name} not found in {SerenaPaths().user_modes_dir} or in {SERENAS_OWN_MODE_YAMLS_DIR}."
                f"Available modes:\n{cls.list_registered_mode_names()}"
            )
        return own_yaml_path

    @classmethod
    def from_name(cls, name: str) -> Self:
        """Load a registered Serena mode."""
        mode_path = cls.get_path(name)
        return cls.from_yaml(mode_path)

    @classmethod
    def from_name_internal(cls, name: str) -> Self:
        """Loads an internal Serena mode"""
        yaml_path = os.path.join(INTERNAL_MODE_YAMLS_DIR, f"{name}.yml")
        if not os.path.exists(yaml_path):
            raise FileNotFoundError(f"Internal mode '{name}' not found in {INTERNAL_MODE_YAMLS_DIR}")
        return cls.from_yaml(yaml_path)

    @classmethod
    def list_registered_mode_names(cls, include_user_modes: bool = True) -> list[str]:
        """Names of all registered modes (from the corresponding YAML files in the serena repo)."""
        modes = [f.stem for f in Path(SERENAS_OWN_MODE_YAMLS_DIR).glob("*.yml") if f.name != "mode.template.yml"]
        if include_user_modes:
            modes += cls.list_custom_mode_names()
        return sorted(set(modes))

    @classmethod
    def list_custom_mode_names(cls) -> list[str]:
        """Names of all custom modes defined by the user."""
        return [f.stem for f in Path(SerenaPaths().user_modes_dir).glob("*.yml")]

    @classmethod
    def load_default_modes(cls) -> list[Self]:
        """Load the default modes (interactive and editing)."""
        return [cls.from_name(mode) for mode in DEFAULT_MODES]

    @classmethod
    def load(cls, name_or_path: str | Path) -> Self:
        # Check if it's a file path that exists
        path = Path(name_or_path)
        if path.exists() and path.is_file():
            return cls.from_yaml(name_or_path)

        # If it looks like a file path but doesn't exist, raise FileNotFoundError
        name_or_path_str = str(name_or_path)
        if os.sep in name_or_path_str or (os.altsep and os.altsep in name_or_path_str) or name_or_path_str.endswith((".yml", ".yaml")):
            raise FileNotFoundError(f"Mode file not found: {path.resolve()}")

        return cls.from_name(str(name_or_path))


@dataclass(kw_only=True)
class SerenaAgentContext(ToolInclusionDefinition, ToStringMixin):
    """Represents a context where the agent is operating (an IDE, a chat, etc.), typically read off a YAML file.
    An agent can only be in a single context at a time.
    The contexts cannot be changed after the agent is running.
    """

    name: str
    """the name of the context"""

    prompt: str
    """
    a Jinja2 template for the generation of the system prompt.
    It is formatted by the agent (see SerenaAgent._format_prompt()).
    """

    description: str = ""

    tool_description_overrides: dict[str, str] = field(default_factory=dict)
    """
    maps tool names to custom descriptions, default descriptions are extracted from the tool docstrings.
    """

    _yaml_path: Path | None = field(default=None, repr=False, compare=False)
    """
    Internal field storing the path to the YAML file this context was loaded from.
    Used to support loading contexts from arbitrary file paths.
    """

    single_project: bool = False
    """
    whether to assume that Serena shall only work on a single project in this context (provided that a project is given
    when Serena is started).
    If set to true and a project is provided at startup, the set of tools is limited to those required by the project's
    concrete configuration, and other tools are excluded completely, allowing the set of tools to be minimal.
    The `activate_project` tool will, therefore, be disabled in this case, as project switching is not allowed.
    """

    def _tostring_includes(self) -> list[str]:
        return ["name"]

    @classmethod
    def from_yaml(cls, yaml_path: str | Path) -> Self:
        """Load a context from a YAML file."""
        yaml_as_path = Path(yaml_path).resolve()
        with yaml_as_path.open(encoding=SERENA_FILE_ENCODING) as f:
            data = yaml.safe_load(f)
        name = data.pop("name", yaml_as_path.stem)
        # Ensure backwards compatibility for tool_description_overrides
        if "tool_description_overrides" not in data:
            data["tool_description_overrides"] = {}
        return cls(name=name, _yaml_path=yaml_as_path, **data)

    @classmethod
    def get_path(cls, name: str, instance: Self | None = None) -> str:
        """Get the path to the YAML file for a context.

        :param name: The name of the context
        :param instance: Optional context instance. If provided and it has a stored path, that path is returned.
        :return: The path to the context's YAML file
        """
        # If we have an instance with a stored path, use that
        if instance is not None and instance._yaml_path is not None:
            return str(instance._yaml_path)

        fname = f"{name}.yml"
        custom_context_path = os.path.join(SerenaPaths().user_contexts_dir, fname)
        if os.path.exists(custom_context_path):
            return custom_context_path

        own_yaml_path = os.path.join(SERENAS_OWN_CONTEXT_YAMLS_DIR, fname)
        if not os.path.exists(own_yaml_path):
            raise FileNotFoundError(
                f"Context {name} not found in {SerenaPaths().user_contexts_dir} or in {SERENAS_OWN_CONTEXT_YAMLS_DIR}."
                f"Available contexts:\n{cls.list_registered_context_names()}"
            )
        return own_yaml_path

    @classmethod
    def from_name(cls, name: str) -> Self:
        """Load a registered Serena context."""
        legacy_name_mapping = {
            "ide-assistant": "claude-code",
        }
        if name in legacy_name_mapping:
            log.warning(
                f"Context name '{name}' is deprecated and has been renamed to '{legacy_name_mapping[name]}'. "
                f"Please update your configuration; refer to the configuration guide for more details: "
                "https://oraios.github.io/serena/02-usage/050_configuration.html#contexts"
            )
            name = legacy_name_mapping[name]
        context_path = cls.get_path(name)
        return cls.from_yaml(context_path)

    @classmethod
    def load(cls, name_or_path: str | Path) -> Self:
        # Check if it's a file path that exists
        path = Path(name_or_path)
        if path.exists() and path.is_file():
            return cls.from_yaml(name_or_path)

        # If it looks like a file path but doesn't exist, raise FileNotFoundError
        name_or_path_str = str(name_or_path)
        if os.sep in name_or_path_str or (os.altsep and os.altsep in name_or_path_str) or name_or_path_str.endswith((".yml", ".yaml")):
            raise FileNotFoundError(f"Context file not found: {path.resolve()}")

        return cls.from_name(str(name_or_path))

    @classmethod
    def list_registered_context_names(cls, include_user_contexts: bool = True) -> list[str]:
        """Names of all registered contexts (from the corresponding YAML files in the serena repo)."""
        contexts = [f.stem for f in Path(SERENAS_OWN_CONTEXT_YAMLS_DIR).glob("*.yml")]
        if include_user_contexts:
            contexts += cls.list_custom_context_names()
        return sorted(set(contexts))

    @classmethod
    def list_custom_context_names(cls) -> list[str]:
        """Names of all custom contexts defined by the user."""
        return [f.stem for f in Path(SerenaPaths().user_contexts_dir).glob("*.yml")]

    @classmethod
    def load_default(cls) -> Self:
        """Load the default context."""
        return cls.from_name(DEFAULT_CONTEXT)

    def print_overview(self) -> None:
        """Print an overview of the mode."""
        print(f"{self.name}:\n {self.description}")
        if self.excluded_tools:
            print(" excluded tools:\n  " + ", ".join(sorted(self.excluded_tools)))

```

--------------------------------------------------------------------------------
/test/solidlsp/fsharp/test_fsharp_basic.py:
--------------------------------------------------------------------------------

```python
import os
import tempfile
import threading
from pathlib import Path
from unittest.mock import Mock, patch

import pytest

from solidlsp import SolidLanguageServer
from solidlsp.language_servers.fsharp_language_server import FSharpLanguageServer
from solidlsp.ls_config import Language
from solidlsp.ls_utils import SymbolUtils


@pytest.mark.fsharp
class TestFSharpLanguageServer:
    @pytest.mark.parametrize("language_server", [Language.FSHARP], indirect=True)
    def test_find_symbol(self, language_server: SolidLanguageServer) -> None:
        """Test finding symbols in the full symbol tree."""
        symbols = language_server.request_full_symbol_tree()

        # Check for main program module symbols
        assert SymbolUtils.symbol_tree_contains_name(symbols, "Program"), "Program module not found in symbol tree"
        assert SymbolUtils.symbol_tree_contains_name(symbols, "main"), "main function not found in symbol tree"

        # Check for Calculator module symbols
        assert SymbolUtils.symbol_tree_contains_name(symbols, "Calculator"), "Calculator module not found in symbol tree"
        assert SymbolUtils.symbol_tree_contains_name(symbols, "add"), "add function not found in symbol tree"
        assert SymbolUtils.symbol_tree_contains_name(symbols, "CalculatorClass"), "CalculatorClass not found in symbol tree"

    @pytest.mark.parametrize("language_server", [Language.FSHARP], indirect=True)
    def test_get_document_symbols_program(self, language_server: SolidLanguageServer) -> None:
        """Test getting document symbols from the main Program.fs file."""
        file_path = os.path.join("Program.fs")
        symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()[0]

        # Look for expected functions and modules
        symbol_names = [s.get("name") for s in symbols]
        assert "main" in symbol_names, "main function not found in Program.fs symbols"

    @pytest.mark.parametrize("language_server", [Language.FSHARP], indirect=True)
    def test_get_document_symbols_calculator(self, language_server: SolidLanguageServer) -> None:
        """Test getting document symbols from Calculator.fs file."""
        file_path = os.path.join("Calculator.fs")
        symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()[0]

        # Look for expected functions
        symbol_names = [s.get("name") for s in symbols]
        expected_symbols = ["add", "subtract", "multiply", "divide", "square", "factorial", "CalculatorClass"]

        for expected in expected_symbols:
            assert expected in symbol_names, f"{expected} function not found in Calculator.fs symbols"

    @pytest.mark.parametrize("language_server", [Language.FSHARP], indirect=True)
    def test_find_referencing_symbols(self, language_server: SolidLanguageServer) -> None:
        """Test finding references using symbol selection range."""
        file_path = os.path.join("Calculator.fs")
        symbols = language_server.request_document_symbols(file_path)

        # Find the 'add' function symbol
        add_symbol = None

        for sym in symbols.iter_symbols():
            if sym.get("name") == "add":
                add_symbol = sym
                break

        assert add_symbol is not None, "Could not find 'add' function symbol in Calculator.fs"

        # Try to find references to the add function
        sel_start = add_symbol["selectionRange"]["start"]
        refs = language_server.request_references(file_path, sel_start["line"], sel_start["character"] + 1)

        # The add function should be referenced in Program.fs
        assert any("Program.fs" in ref.get("relativePath", "") for ref in refs), "Program.fs should reference add function"

    @pytest.mark.parametrize("language_server", [Language.FSHARP], indirect=True)
    def test_nested_module_symbols(self, language_server: SolidLanguageServer) -> None:
        """Test getting symbols from nested Models namespace."""
        file_path = os.path.join("Models", "Person.fs")
        symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots()[0]

        # Check for expected types and modules
        symbol_names = [s.get("name") for s in symbols]
        expected_symbols = ["Person", "PersonModule", "Address", "Employee"]

        for expected in expected_symbols:
            assert expected in symbol_names, f"{expected} not found in Person.fs symbols"

    @pytest.mark.parametrize("language_server", [Language.FSHARP], indirect=True)
    def test_find_referencing_symbols_across_files(self, language_server: SolidLanguageServer) -> None:
        """Test finding references to Calculator functions across files."""
        # Find the subtract function in Calculator.fs
        file_path = os.path.join("Calculator.fs")
        symbols = language_server.request_document_symbols(file_path)

        subtract_symbol = None
        for sym in symbols.iter_symbols():
            if sym.get("name") == "subtract":
                subtract_symbol = sym
                break

        assert subtract_symbol is not None, "Could not find 'subtract' function symbol"

        # Find references to subtract function
        sel_start = subtract_symbol["selectionRange"]["start"]
        refs = language_server.request_references(file_path, sel_start["line"], sel_start["character"] + 1)

        # The subtract function should be referenced in Program.fs
        assert any("Program.fs" in ref.get("relativePath", "") for ref in refs), "Program.fs should reference subtract function"

    @pytest.mark.parametrize("language_server", [Language.FSHARP], indirect=True)
    def test_go_to_definition(self, language_server: SolidLanguageServer) -> None:
        """Test go-to-definition functionality."""
        # Test going to definition of 'add' function from Program.fs
        program_file = os.path.join("Program.fs")

        # Try to find definition of 'add' function used in Program.fs
        # This would typically be at the line where 'add 5 3' is called
        definitions = language_server.request_definition(program_file, 10, 20)  # Approximate position

        # We should get at least some definitions
        assert len(definitions) >= 0, "Should get definitions (even if empty for complex cases)"

    @pytest.mark.parametrize("language_server", [Language.FSHARP], indirect=True)
    def test_hover_information(self, language_server: SolidLanguageServer) -> None:
        """Test hover information functionality."""
        file_path = os.path.join("Calculator.fs")

        # Try to get hover information for a function
        hover_info = language_server.request_hover(file_path, 5, 10)  # Approximate position of a function

        # Hover info might be None or contain information
        # This is acceptable as it depends on the LSP server's capabilities and timing
        assert hover_info is None or isinstance(hover_info, dict), "Hover info should be None or dict"

    @pytest.mark.parametrize("language_server", [Language.FSHARP], indirect=True)
    def test_completion(self, language_server: SolidLanguageServer) -> None:
        """Test code completion functionality."""
        file_path = os.path.join("Program.fs")

        # Use threading for cross-platform timeout (signal.SIGALRM is Unix-only)
        result = [None]
        exception = [None]

        def run_completion():
            try:
                result[0] = language_server.request_completions(file_path, 15, 10)
            except Exception as e:
                exception[0] = e

        thread = threading.Thread(target=run_completion, daemon=True)
        thread.start()
        thread.join(timeout=5)  # 5 second timeout

        if thread.is_alive():
            # Completion timed out, but this is acceptable for F# in some cases
            # The important thing is that the language server doesn't crash
            return

        if exception[0]:
            raise exception[0]

        assert isinstance(result[0], list), "Completions should be a list"

    @pytest.mark.parametrize("language_server", [Language.FSHARP], indirect=True)
    def test_diagnostics(self, language_server: SolidLanguageServer) -> None:
        """Test getting diagnostics (errors, warnings) from F# files."""
        file_path = os.path.join("Program.fs")

        # FsAutoComplete uses publishDiagnostics notifications instead of textDocument/diagnostic requests
        # So we'll test that the language server can handle files without crashing
        # In real usage, diagnostics would come through the publishDiagnostics notification handler

        # Test that we can at least work with the file (open/close cycle)
        with language_server.open_file(file_path) as _:
            # If we can open and close the file without errors, basic diagnostics support is working
            pass

        # This is a successful test - FsAutoComplete is working with F# files
        assert True, "F# language server can handle files successfully"


@pytest.mark.fsharp
class TestFSharpLanguageServerSetup:
    """Test F# language server setup and configuration."""

    def test_runtime_dependency_setup_without_dotnet(self) -> None:
        """Test that setup fails gracefully when .NET is not installed."""
        with patch("shutil.which", return_value=None):
            with pytest.raises(RuntimeError, match=r"\.NET SDK is not installed"):
                FSharpLanguageServer._setup_runtime_dependencies(Mock(), Mock())

    def test_runtime_dependency_setup_with_dotnet(self) -> None:
        """Test that setup works when .NET is available."""
        mock_config = Mock()
        mock_settings = Mock()

        # Mock the ls_resources_dir to return a temp directory
        with tempfile.TemporaryDirectory() as temp_dir:
            with patch("shutil.which", return_value="/usr/bin/dotnet"):
                with patch.object(FSharpLanguageServer, "ls_resources_dir", return_value=temp_dir):
                    with patch("subprocess.run") as mock_run:
                        # Mock successful dotnet version check
                        mock_run.return_value.stdout = "8.0.100"
                        mock_run.return_value.returncode = 0

                        # Create a fake fsautocomplete executable
                        fsharp_dir = os.path.join(temp_dir, "fsharp-lsp")
                        os.makedirs(fsharp_dir, exist_ok=True)
                        # Use .exe extension on Windows, matching production code
                        exe_name = "fsautocomplete.exe" if os.name == "nt" else "fsautocomplete"
                        fsautocomplete_path = os.path.join(fsharp_dir, exe_name)
                        Path(fsautocomplete_path).touch()

                        result = FSharpLanguageServer._setup_runtime_dependencies(mock_config, mock_settings)

                        assert fsautocomplete_path in result
                        assert "--adaptive-lsp-server-enabled --project-graph-enabled --use-fcs-transparent-compiler" in result

```

--------------------------------------------------------------------------------
/test/solidlsp/clojure/test_clojure_basic.py:
--------------------------------------------------------------------------------

```python
import pytest

from serena.project import Project
from solidlsp.ls import SolidLanguageServer
from solidlsp.ls_config import Language
from solidlsp.ls_types import UnifiedSymbolInformation
from test.conftest import language_tests_enabled

from . import CORE_PATH, UTILS_PATH


@pytest.mark.skipif(not language_tests_enabled(Language.CLOJURE), reason="Clojure tests are disabled")
@pytest.mark.clojure
class TestLanguageServerBasics:
    @pytest.mark.parametrize("language_server", [Language.CLOJURE], indirect=True)
    def test_basic_definition(self, language_server: SolidLanguageServer):
        """
        Test finding definition of 'greet' function call in core.clj
        """
        result = language_server.request_definition(CORE_PATH, 20, 12)  # Position of 'greet' in (greet "World")

        assert isinstance(result, list)
        assert len(result) >= 1

        definition = result[0]
        assert definition["relativePath"] == CORE_PATH
        assert definition["range"]["start"]["line"] == 2, "Should find the definition of greet function at line 2"

    @pytest.mark.parametrize("language_server", [Language.CLOJURE], indirect=True)
    def test_cross_file_references(self, language_server: SolidLanguageServer):
        """
        Test finding references to 'multiply' function from core.clj
        """
        result = language_server.request_references(CORE_PATH, 12, 6)

        assert isinstance(result, list) and len(result) >= 2, "Should find definition + usage in utils.clj"

        usage_found = any(
            item["relativePath"] == UTILS_PATH and item["range"]["start"]["line"] == 6  # multiply usage in calculate-area
            for item in result
        )
        assert usage_found, "Should find multiply usage in utils.clj"

    @pytest.mark.parametrize("language_server", [Language.CLOJURE], indirect=True)
    def test_completions(self, language_server: SolidLanguageServer):
        with language_server.open_file(UTILS_PATH):
            # After "core/" in calculate-area
            result = language_server.request_completions(UTILS_PATH, 6, 8)

            assert isinstance(result, list) and len(result) > 0

            completion_texts = [item["completionText"] for item in result]
            assert any("multiply" in text for text in completion_texts), "Should find 'multiply' function in completions after 'core/'"

    @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).get_all_symbols_and_roots()

        assert isinstance(symbols, list) and len(symbols) >= 4, "greet, add, multiply, -main functions"

        # Check that we find the expected function symbols
        symbol_names = [symbol["name"] for symbol in symbols]
        expected_functions = ["greet", "add", "multiply", "-main"]

        for func_name in expected_functions:
            assert func_name in symbol_names, f"Should find {func_name} function in symbols"

    @pytest.mark.parametrize("language_server", [Language.CLOJURE], indirect=True)
    def test_hover(self, language_server: SolidLanguageServer):
        """Test hover on greet function"""
        result = language_server.request_hover(CORE_PATH, 2, 7)

        assert result is not None, "Hover should return information for greet function"
        assert "contents" in result
        # Should contain function signature or documentation
        contents = result["contents"]
        if isinstance(contents, str):
            assert "greet" in contents.lower()
        elif isinstance(contents, dict) and "value" in contents:
            assert "greet" in contents["value"].lower()
        else:
            assert False, f"Unexpected contents format: {type(contents)}"

    @pytest.mark.parametrize("language_server", [Language.CLOJURE], indirect=True)
    def test_workspace_symbols(self, language_server: SolidLanguageServer):
        # Search for functions containing "add"
        result = language_server.request_workspace_symbol("add")

        assert isinstance(result, list) and len(result) > 0, "Should find at least one symbol containing 'add'"

        # Should find the 'add' function
        symbol_names = [symbol["name"] for symbol in result]
        assert any("add" in name.lower() for name in symbol_names), f"Should find 'add' function in symbols: {symbol_names}"

    @pytest.mark.parametrize("language_server", [Language.CLOJURE], indirect=True)
    def test_namespace_functions(self, language_server: SolidLanguageServer):
        """Test definition lookup for core/greet usage in utils.clj"""
        # Position of 'greet' in core/greet call
        result = language_server.request_definition(UTILS_PATH, 11, 25)

        assert isinstance(result, list)
        assert len(result) >= 1

        definition = result[0]
        assert definition["relativePath"] == CORE_PATH, "Should find the definition of greet in core.clj"

    @pytest.mark.parametrize("language_server", [Language.CLOJURE], indirect=True)
    def test_request_references_with_content(self, language_server: SolidLanguageServer):
        """Test references to multiply function with content"""
        references = language_server.request_references(CORE_PATH, 12, 6)
        result = [
            language_server.retrieve_content_around_line(ref1["relativePath"], ref1["range"]["start"]["line"], 3, 0) for ref1 in references
        ]

        assert result is not None, "Should find references with content"
        assert isinstance(result, list)
        assert len(result) >= 2, "Should find definition + usage in utils.clj"

        for ref in result:
            assert ref.source_file_path is not None, "Each reference should have a source file path"
            content_str = ref.to_display_string()
            assert len(content_str) > 0, "Content should not be empty"

        # Verify we find the reference in utils.clj with context
        utils_refs = [ref for ref in result if ref.source_file_path and "utils.clj" in ref.source_file_path]
        assert len(utils_refs) > 0, "Should find reference in utils.clj"

        # The context should contain the calculate-area function
        utils_content = utils_refs[0].to_display_string()
        assert "calculate-area" in utils_content

    @pytest.mark.parametrize("language_server", [Language.CLOJURE], indirect=True)
    def test_request_full_symbol_tree(self, language_server: SolidLanguageServer):
        """Test retrieving the full symbol tree for project overview
        We just check that we find some expected symbols.
        """
        result = language_server.request_full_symbol_tree()

        assert result is not None, "Should return symbol tree"
        assert isinstance(result, list), "Symbol tree should be a list"
        assert len(result) > 0, "Should find symbols in the project"

        def traverse_symbols(symbols, indent=0):
            """Recursively traverse symbols to print their structure"""
            info = []
            for s in symbols:
                name = getattr(s, "name", "NO_NAME")
                kind = getattr(s, "kind", "NO_KIND")
                info.append(f"{' ' * indent}Symbol: {name}, Kind: {kind}")
                if hasattr(s, "children") and s.children:
                    info.append(" " * indent + "Children:")
                    info.extend(traverse_symbols(s.children, indent + 2))
            return info

        def list_all_symbols(symbols: list[UnifiedSymbolInformation]):
            found = []
            for symbol in symbols:
                found.append(symbol["name"])
                found.extend(list_all_symbols(symbol["children"]))
            return found

        all_symbol_names = list_all_symbols(result)

        expected_symbols = ["greet", "add", "multiply", "-main", "calculate-area", "format-greeting", "sum-list"]
        found_expected = [name for name in expected_symbols if any(name in symbol_name for symbol_name in all_symbol_names)]

        if len(found_expected) < 7:
            pytest.fail(
                f"Expected to find at least 3 symbols from {expected_symbols}, but found: {found_expected}.\n"
                f"All symbol names: {all_symbol_names}\n"
                f"Symbol tree structure:\n{traverse_symbols(result)}"
            )

    @pytest.mark.parametrize("language_server", [Language.CLOJURE], indirect=True)
    def test_request_referencing_symbols(self, language_server: SolidLanguageServer):
        """Test finding symbols that reference a given symbol
        Finds references to the 'multiply' function.
        """
        result = language_server.request_referencing_symbols(CORE_PATH, 12, 6)
        assert isinstance(result, list) and len(result) > 0, "Should find at least one referencing symbol"
        found_relevant_references = False
        for ref in result:
            if hasattr(ref, "symbol") and "calculate-area" in ref.symbol["name"]:
                found_relevant_references = True
                break

        assert found_relevant_references, f"Should have found calculate-area referencing multiply, but got: {result}"


class TestProjectBasics:
    @pytest.mark.parametrize("project", [Language.CLOJURE], indirect=True)
    def test_retrieve_content_around_line(self, project: Project):
        """Test retrieving content around specific lines"""
        # Test retrieving content around the greet function definition (line 2)
        result = project.retrieve_content_around_line(CORE_PATH, 2, 2)

        assert result is not None, "Should retrieve content around line 2"
        content_str = result.to_display_string()
        assert "greet" in content_str, "Should contain the greet function definition"
        assert "defn" in content_str, "Should contain defn keyword"

        # Test retrieving content around multiply function (around line 13)
        result = project.retrieve_content_around_line(CORE_PATH, 13, 1)

        assert result is not None, "Should retrieve content around line 13"
        content_str = result.to_display_string()
        assert "multiply" in content_str, "Should contain multiply function"

    @pytest.mark.parametrize("project", [Language.CLOJURE], indirect=True)
    def test_search_files_for_pattern(self, project: Project) -> None:
        result = project.search_source_files_for_pattern("defn.*greet")

        assert result is not None, "Pattern search should return results"
        assert len(result) > 0, "Should find at least one match for 'defn.*greet'"

        core_matches = [match for match in result if match.source_file_path and "core.clj" in match.source_file_path]
        assert len(core_matches) > 0, "Should find greet function in core.clj"

        result = project.search_source_files_for_pattern(":require")

        assert result is not None, "Should find require statements"
        utils_matches = [match for match in result if match.source_file_path and "utils.clj" in match.source_file_path]
        assert len(utils_matches) > 0, "Should find require statement in utils.clj"

```

--------------------------------------------------------------------------------
/test/solidlsp/nix/test_nix_basic.py:
--------------------------------------------------------------------------------

```python
"""
Tests for the Nix language server implementation using nixd.

These tests validate symbol finding and cross-file reference capabilities for Nix expressions.
"""

import platform

import pytest

from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language

# Skip all Nix tests on Windows as Nix doesn't support Windows
pytestmark = pytest.mark.skipif(platform.system() == "Windows", reason="Nix and nil are not available on Windows")


@pytest.mark.nix
class TestNixLanguageServer:
    """Test Nix language server symbol finding capabilities."""

    @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").get_all_symbols_and_roots()

        assert symbols is not None
        assert len(symbols) > 0

        # Extract symbol names from the returned structure
        symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
        symbol_names = {sym.get("name") for sym in symbol_list if isinstance(sym, dict)}

        # Verify specific function exists
        assert "makeGreeting" in symbol_names, "makeGreeting function not found"

        # Verify exact attribute sets are found
        expected_attrs = {"listUtils", "stringUtils"}
        found_attrs = symbol_names & expected_attrs
        assert found_attrs == expected_attrs, f"Expected exactly {expected_attrs}, found {found_attrs}"

    @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").get_all_symbols_and_roots()

        assert symbols is not None
        assert len(symbols) > 0

        symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
        symbol_names = {sym.get("name") for sym in symbol_list if isinstance(sym, dict)}

        # Verify exact utility modules are found
        expected_modules = {"math", "strings", "lists", "attrs"}
        found_modules = symbol_names & expected_modules
        assert found_modules == expected_modules, f"Expected exactly {expected_modules}, found {found_modules}"

    @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").get_all_symbols_and_roots()

        assert symbols is not None
        assert len(symbols) > 0

        symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
        symbol_names = {sym.get("name") for sym in symbol_list if isinstance(sym, dict)}

        # Flakes must have either inputs or outputs
        assert "inputs" in symbol_names or "outputs" in symbol_names, "Flake must have inputs or outputs"

    @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").get_all_symbols_and_roots()

        assert symbols is not None
        assert len(symbols) > 0

        symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
        symbol_names = {sym.get("name") for sym in symbol_list if isinstance(sym, dict)}

        # NixOS modules must have either options or config
        assert "options" in symbol_names or "config" in symbol_names, "Module must have options or config"

    @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").get_all_symbols_and_roots()

        assert symbols is not None
        symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols

        # Find makeGreeting function
        greeting_symbol = None
        for sym in symbol_list:
            if sym.get("name") == "makeGreeting":
                greeting_symbol = sym
                break

        assert greeting_symbol is not None, "makeGreeting function not found"
        assert "range" in greeting_symbol, "Symbol must have range information"

        range_start = greeting_symbol["range"]["start"]
        refs = language_server.request_references("default.nix", range_start["line"], range_start["character"])

        assert refs is not None
        assert isinstance(refs, list)
        # nixd finds at least the inherit statement (line 67)
        assert len(refs) >= 1, f"Should find at least 1 reference to makeGreeting, found {len(refs)}"

        # Verify makeGreeting is referenced at expected locations
        if refs:
            ref_lines = sorted([ref["range"]["start"]["line"] for ref in refs])
            # Check if we found the inherit (line 67, 0-indexed: 66)
            assert 66 in ref_lines, f"Should find makeGreeting inherit at line 67, found at lines {[l+1 for l in ref_lines]}"

    @pytest.mark.parametrize("language_server", [Language.NIX], indirect=True)
    def test_hover_information(self, language_server: SolidLanguageServer) -> None:
        """Test hover information for symbols."""
        # Get hover info for makeGreeting function
        hover_info = language_server.request_hover("default.nix", 9, 5)  # Position near makeGreeting

        assert hover_info is not None, "Should provide hover information"

        if isinstance(hover_info, dict) and len(hover_info) > 0:
            # If hover info is provided, it should have proper structure
            assert "contents" in hover_info or "value" in hover_info, "Hover should have contents or value"

    @pytest.mark.parametrize("language_server", [Language.NIX], indirect=True)
    def test_cross_file_references_utils_import(self, language_server: SolidLanguageServer) -> None:
        """Test finding cross-file references for imported utils."""
        # Find references to 'utils' which is imported in default.nix from lib/utils.nix
        # Line 10 in default.nix: utils = import ./lib/utils.nix { inherit lib; };
        refs = language_server.request_references("default.nix", 9, 2)  # Position of 'utils'

        assert refs is not None
        assert isinstance(refs, list)

        # Should find references within default.nix where utils is used
        default_refs = [ref for ref in refs if "default.nix" in ref.get("uri", "")]
        # utils is: imported (line 10), used in listUtils.unique (line 24), inherited in exports (line 69)
        assert len(default_refs) >= 2, f"Should find at least 2 references to utils in default.nix, found {len(default_refs)}"

        # Verify utils is referenced at expected locations (0-indexed)
        if default_refs:
            ref_lines = sorted([ref["range"]["start"]["line"] for ref in default_refs])
            # Check for key references - at least the import (line 10) or usage (line 24)
            assert (
                9 in ref_lines or 23 in ref_lines
            ), f"Should find utils import or usage, found references at lines {[l+1 for l in ref_lines]}"

    @pytest.mark.parametrize("language_server", [Language.NIX], indirect=True)
    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").get_all_symbols_and_roots()

        assert symbols is not None
        symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols

        # Check that makeGreeting exists (defined in default.nix)
        symbol_names = {sym.get("name") for sym in symbol_list if isinstance(sym, dict)}
        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").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)}

        # Verify key functions exist in utils
        assert "math" in utils_names, "math should be found in lib/utils.nix"
        assert "strings" in utils_names, "strings should be found in lib/utils.nix"

    @pytest.mark.parametrize("language_server", [Language.NIX], indirect=True)
    def test_go_to_definition_cross_file(self, language_server: SolidLanguageServer) -> None:
        """Test go-to-definition from default.nix to lib/utils.nix."""
        # Line 24 in default.nix: unique = utils.lists.unique;
        # Test go-to-definition for 'utils'
        definitions = language_server.request_definition("default.nix", 23, 14)  # Position of 'utils'

        assert definitions is not None
        assert isinstance(definitions, list)

        if len(definitions) > 0:
            # Should point to the import statement or utils.nix
            assert any(
                "utils" in def_item.get("uri", "") or "default.nix" in def_item.get("uri", "") for def_item in definitions
            ), "Definition should relate to utils import or utils.nix file"

    @pytest.mark.parametrize("language_server", [Language.NIX], indirect=True)
    def test_definition_navigation_in_flake(self, language_server: SolidLanguageServer) -> None:
        """Test definition navigation in flake.nix."""
        # Test that we can navigate to definitions within flake.nix
        # Line 69: default = hello-custom;
        definitions = language_server.request_definition("flake.nix", 68, 20)  # Position of 'hello-custom'

        assert definitions is not None
        assert isinstance(definitions, list)
        # nixd should find the definition of hello-custom in the same file
        if len(definitions) > 0:
            assert any(
                "flake.nix" in def_item.get("uri", "") for def_item in definitions
            ), "Should find hello-custom definition in flake.nix"

    @pytest.mark.parametrize("language_server", [Language.NIX], indirect=True)
    def test_full_symbol_tree(self, language_server: SolidLanguageServer) -> None:
        """Test that full symbol tree is not empty."""
        symbols = language_server.request_full_symbol_tree()

        assert symbols is not None
        assert len(symbols) > 0, "Symbol tree should not be empty"

        # The tree should have at least one root node
        root = symbols[0]
        assert isinstance(root, dict), "Root should be a dict"
        assert "name" in root, "Root should have a name"

```

--------------------------------------------------------------------------------
/src/solidlsp/language_servers/lua_ls.py:
--------------------------------------------------------------------------------

```python
"""
Provides Lua specific instantiation of the LanguageServer class using lua-language-server.
"""

import logging
import os
import pathlib
import platform
import shutil
import tarfile
import threading
import zipfile
from pathlib import Path

import requests
from overrides import override

from solidlsp.ls import SolidLanguageServer
from solidlsp.ls_config import LanguageServerConfig
from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams
from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo
from solidlsp.settings import SolidLSPSettings

log = logging.getLogger(__name__)


class LuaLanguageServer(SolidLanguageServer):
    """
    Provides Lua specific instantiation of the LanguageServer class using lua-language-server.
    """

    @override
    def is_ignored_dirname(self, dirname: str) -> bool:
        # For Lua projects, we should ignore:
        # - .luarocks: package manager cache
        # - lua_modules: local dependencies
        # - node_modules: if the project has JavaScript components
        return super().is_ignored_dirname(dirname) or dirname in [".luarocks", "lua_modules", "node_modules", "build", "dist", ".cache"]

    @staticmethod
    def _get_lua_ls_path() -> str | None:
        """Get the path to lua-language-server executable."""
        # First check if it's in PATH
        lua_ls = shutil.which("lua-language-server")
        if lua_ls:
            return lua_ls

        # Check common installation locations
        home = Path.home()
        possible_paths = [
            home / ".local" / "bin" / "lua-language-server",
            home / ".serena" / "language_servers" / "lua" / "bin" / "lua-language-server",
            Path("/usr/local/bin/lua-language-server"),
            Path("/opt/lua-language-server/bin/lua-language-server"),
        ]

        # Add Windows-specific paths
        if platform.system() == "Windows":
            possible_paths.extend(
                [
                    home / "AppData" / "Local" / "lua-language-server" / "bin" / "lua-language-server.exe",
                    home / ".serena" / "language_servers" / "lua" / "bin" / "lua-language-server.exe",
                ]
            )

        for path in possible_paths:
            if path.exists():
                return str(path)

        return None

    @staticmethod
    def _download_lua_ls() -> str:
        """Download and install lua-language-server if not present."""
        system = platform.system()
        machine = platform.machine().lower()
        lua_ls_version = "3.15.0"

        # Map platform and architecture to download URL
        if system == "Linux":
            if machine in ["x86_64", "amd64"]:
                download_name = f"lua-language-server-{lua_ls_version}-linux-x64.tar.gz"
            elif machine in ["aarch64", "arm64"]:
                download_name = f"lua-language-server-{lua_ls_version}-linux-arm64.tar.gz"
            else:
                raise RuntimeError(f"Unsupported Linux architecture: {machine}")
        elif system == "Darwin":
            if machine in ["x86_64", "amd64"]:
                download_name = f"lua-language-server-{lua_ls_version}-darwin-x64.tar.gz"
            elif machine in ["arm64", "aarch64"]:
                download_name = f"lua-language-server-{lua_ls_version}-darwin-arm64.tar.gz"
            else:
                raise RuntimeError(f"Unsupported macOS architecture: {machine}")
        elif system == "Windows":
            if machine in ["amd64", "x86_64"]:
                download_name = f"lua-language-server-{lua_ls_version}-win32-x64.zip"
            else:
                raise RuntimeError(f"Unsupported Windows architecture: {machine}")
        else:
            raise RuntimeError(f"Unsupported operating system: {system}")

        download_url = f"https://github.com/LuaLS/lua-language-server/releases/download/{lua_ls_version}/{download_name}"

        # Create installation directory
        install_dir = Path.home() / ".serena" / "language_servers" / "lua"
        install_dir.mkdir(parents=True, exist_ok=True)

        # Download the file
        print(f"Downloading lua-language-server from {download_url}...")
        response = requests.get(download_url, stream=True)
        response.raise_for_status()

        # Save and extract
        download_path = install_dir / download_name
        with open(download_path, "wb") as f:
            for chunk in response.iter_content(chunk_size=8192):
                f.write(chunk)

        print(f"Extracting lua-language-server to {install_dir}...")
        if download_name.endswith(".tar.gz"):
            with tarfile.open(download_path, "r:gz") as tar:
                tar.extractall(install_dir)
        elif download_name.endswith(".zip"):
            with zipfile.ZipFile(download_path, "r") as zip_ref:
                zip_ref.extractall(install_dir)

        # Clean up download file
        download_path.unlink()

        # Make executable on Unix systems
        if system != "Windows":
            lua_ls_path = install_dir / "bin" / "lua-language-server"
            if lua_ls_path.exists():
                lua_ls_path.chmod(0o755)
                return str(lua_ls_path)
        else:
            lua_ls_path = install_dir / "bin" / "lua-language-server.exe"
            if lua_ls_path.exists():
                return str(lua_ls_path)

        raise RuntimeError("Failed to find lua-language-server executable after extraction")

    @staticmethod
    def _setup_runtime_dependency() -> str:
        """
        Check if required Lua runtime dependencies are available.
        Downloads lua-language-server if not present.
        """
        lua_ls_path = LuaLanguageServer._get_lua_ls_path()

        if not lua_ls_path:
            print("lua-language-server not found. Downloading...")
            lua_ls_path = LuaLanguageServer._download_lua_ls()
            print(f"lua-language-server installed at: {lua_ls_path}")

        return lua_ls_path

    def __init__(self, config: LanguageServerConfig, repository_root_path: str, solidlsp_settings: SolidLSPSettings):
        lua_ls_path = self._setup_runtime_dependency()

        super().__init__(
            config, repository_root_path, ProcessLaunchInfo(cmd=lua_ls_path, cwd=repository_root_path), "lua", solidlsp_settings
        )
        self.server_ready = threading.Event()
        self.request_id = 0

    @staticmethod
    def _get_initialize_params(repository_absolute_path: str) -> InitializeParams:
        """
        Returns the initialize params for the Lua Language Server.
        """
        root_uri = pathlib.Path(repository_absolute_path).as_uri()
        initialize_params = {
            "locale": "en",
            "capabilities": {
                "textDocument": {
                    "synchronization": {"didSave": True, "dynamicRegistration": True},
                    "definition": {"dynamicRegistration": True},
                    "references": {"dynamicRegistration": True},
                    "documentSymbol": {
                        "dynamicRegistration": True,
                        "hierarchicalDocumentSymbolSupport": True,
                        "symbolKind": {"valueSet": list(range(1, 27))},
                    },
                    "completion": {
                        "dynamicRegistration": True,
                        "completionItem": {
                            "snippetSupport": True,
                            "commitCharactersSupport": True,
                            "documentationFormat": ["markdown", "plaintext"],
                            "deprecatedSupport": True,
                            "preselectSupport": True,
                        },
                    },
                    "hover": {
                        "dynamicRegistration": True,
                        "contentFormat": ["markdown", "plaintext"],
                    },
                    "signatureHelp": {
                        "dynamicRegistration": True,
                        "signatureInformation": {
                            "documentationFormat": ["markdown", "plaintext"],
                            "parameterInformation": {"labelOffsetSupport": True},
                        },
                    },
                },
                "workspace": {
                    "workspaceFolders": True,
                    "didChangeConfiguration": {"dynamicRegistration": True},
                    "configuration": True,
                    "symbol": {
                        "dynamicRegistration": True,
                        "symbolKind": {"valueSet": list(range(1, 27))},
                    },
                },
            },
            "processId": os.getpid(),
            "rootPath": repository_absolute_path,
            "rootUri": root_uri,
            "workspaceFolders": [
                {
                    "uri": root_uri,
                    "name": os.path.basename(repository_absolute_path),
                }
            ],
            "initializationOptions": {
                # Lua Language Server specific options
                "runtime": {
                    "version": "Lua 5.4",
                    "path": ["?.lua", "?/init.lua"],
                },
                "diagnostics": {
                    "enable": True,
                    "globals": ["vim", "describe", "it", "before_each", "after_each"],  # Common globals
                },
                "workspace": {
                    "library": [],  # Can be extended with project-specific libraries
                    "checkThirdParty": False,
                    "userThirdParty": [],
                },
                "telemetry": {
                    "enable": False,
                },
                "completion": {
                    "enable": True,
                    "callSnippet": "Both",
                    "keywordSnippet": "Both",
                },
            },
        }
        return initialize_params  # type: ignore[return-value]

    def _start_server(self) -> None:
        """Start Lua Language Server process"""

        def register_capability_handler(params: dict) -> None:
            return

        def window_log_message(msg: dict) -> None:
            log.info(f"LSP: window/logMessage: {msg}")

        def do_nothing(params: dict) -> None:
            return

        self.server.on_request("client/registerCapability", register_capability_handler)
        self.server.on_notification("window/logMessage", window_log_message)
        self.server.on_notification("$/progress", do_nothing)
        self.server.on_notification("textDocument/publishDiagnostics", do_nothing)

        log.info("Starting Lua Language Server process")
        self.server.start()
        initialize_params = self._get_initialize_params(self.repository_root_path)

        log.info("Sending initialize request from LSP client to LSP server and awaiting response")
        init_response = self.server.send.initialize(initialize_params)

        # Verify server capabilities
        assert "textDocumentSync" in init_response["capabilities"]
        assert "definitionProvider" in init_response["capabilities"]
        assert "documentSymbolProvider" in init_response["capabilities"]
        assert "referencesProvider" in init_response["capabilities"]

        self.server.notify.initialized({})
        self.completions_available.set()

        # Lua Language Server is typically ready immediately after initialization
        self.server_ready.set()
        self.server_ready.wait()

```

--------------------------------------------------------------------------------
/test/solidlsp/lua/test_lua_basic.py:
--------------------------------------------------------------------------------

```python
"""
Tests for the Lua language server implementation.

These tests validate symbol finding and cross-file reference capabilities
for Lua modules and functions.
"""

import pytest

from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language
from solidlsp.ls_types import SymbolKind


@pytest.mark.lua
class TestLuaLanguageServer:
    """Test Lua language server symbol finding and cross-file references."""

    @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").get_all_symbols_and_roots()

        assert symbols is not None
        assert len(symbols) > 0

        # Extract function names from the returned structure
        symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
        function_names = set()
        for symbol in symbol_list:
            if isinstance(symbol, dict):
                name = symbol.get("name", "")
                # Handle both plain names and module-prefixed names
                if "." in name:
                    name = name.split(".")[-1]
                if symbol.get("kind") == SymbolKind.Function:
                    function_names.add(name)

        # Verify exact calculator functions exist
        expected_functions = {"add", "subtract", "multiply", "divide", "factorial"}
        found_functions = function_names & expected_functions
        assert found_functions == expected_functions, f"Expected exactly {expected_functions}, found {found_functions}"

        # Verify specific functions
        assert "add" in function_names, "add function not found"
        assert "multiply" in function_names, "multiply function not found"
        assert "factorial" in function_names, "factorial function not found"

    @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").get_all_symbols_and_roots()

        assert symbols is not None
        assert len(symbols) > 0

        symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
        function_names = set()
        all_symbols = set()

        for symbol in symbol_list:
            if isinstance(symbol, dict):
                name = symbol.get("name", "")
                all_symbols.add(name)
                # Handle both plain names and module-prefixed names
                if "." in name:
                    name = name.split(".")[-1]
                if symbol.get("kind") == SymbolKind.Function:
                    function_names.add(name)

        # Verify exact string utility functions
        expected_utils = {"trim", "split", "starts_with", "ends_with"}
        found_utils = function_names & expected_utils
        assert found_utils == expected_utils, f"Expected exactly {expected_utils}, found {found_utils}"

        # Verify exact table utility functions
        table_utils = {"deep_copy", "table_contains", "table_merge"}
        found_table_utils = function_names & table_utils
        assert found_table_utils == table_utils, f"Expected exactly {table_utils}, found {found_table_utils}"

        # Check for Logger class/table
        assert "Logger" in all_symbols or any("Logger" in s for s in all_symbols), "Logger not found in symbols"

    @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").get_all_symbols_and_roots()

        assert symbols is not None
        assert len(symbols) > 0

        symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols
        function_names = set()

        for symbol in symbol_list:
            if isinstance(symbol, dict) and symbol.get("kind") == SymbolKind.Function:
                function_names.add(symbol.get("name", ""))

        # Verify exact main functions exist
        expected_funcs = {"print_banner", "test_calculator", "test_utils"}
        found_funcs = function_names & expected_funcs
        assert found_funcs == expected_funcs, f"Expected exactly {expected_funcs}, found {found_funcs}"

        assert "test_calculator" in function_names, "test_calculator function not found"
        assert "test_utils" in function_names, "test_utils function not found"

    @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").get_all_symbols_and_roots()

        assert symbols is not None
        symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols

        # Find the add function
        add_symbol = None
        for sym in symbol_list:
            if isinstance(sym, dict):
                name = sym.get("name", "")
                if "add" in name or name == "add":
                    add_symbol = sym
                    break

        assert add_symbol is not None, "add function not found in calculator.lua"

        # Get references to the add function
        range_info = add_symbol.get("selectionRange", add_symbol.get("range"))
        assert range_info is not None, "add function has no range information"

        range_start = range_info["start"]
        refs = language_server.request_references("src/calculator.lua", range_start["line"], range_start["character"])

        assert refs is not None
        assert isinstance(refs, list)
        # add function appears in: main.lua (lines 16, 71), test_calculator.lua (lines 22, 23, 24)
        # Note: The declaration itself may or may not be included as a reference
        assert len(refs) >= 5, f"Should find at least 5 references to calculator.add, found {len(refs)}"

        # Verify exact reference locations
        ref_files = {}
        for ref in refs:
            filename = ref.get("uri", "").split("/")[-1]
            if filename not in ref_files:
                ref_files[filename] = []
            ref_files[filename].append(ref["range"]["start"]["line"])

        # The declaration may or may not be included
        if "calculator.lua" in ref_files:
            assert (
                5 in ref_files["calculator.lua"]
            ), f"If declaration is included, it should be at line 6 (0-indexed: 5), found at {ref_files['calculator.lua']}"

        # Check main.lua has usages
        assert "main.lua" in ref_files, "Should find add usages in main.lua"
        assert (
            15 in ref_files["main.lua"] or 70 in ref_files["main.lua"]
        ), f"Should find add usage in main.lua, found at lines {ref_files.get('main.lua', [])}"

        # Check for cross-file references from main.lua
        main_refs = [ref for ref in refs if "main.lua" in ref.get("uri", "")]
        assert len(main_refs) > 0, "calculator.add should be called in main.lua"

    @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").get_all_symbols_and_roots()

        assert symbols is not None
        symbol_list = symbols[0] if isinstance(symbols, tuple) else symbols

        # Find the trim function
        trim_symbol = None
        for sym in symbol_list:
            if isinstance(sym, dict):
                name = sym.get("name", "")
                if "trim" in name or name == "trim":
                    trim_symbol = sym
                    break

        assert trim_symbol is not None, "trim function not found in utils.lua"

        # Get references to the trim function
        range_info = trim_symbol.get("selectionRange", trim_symbol.get("range"))
        assert range_info is not None, "trim function has no range information"

        range_start = range_info["start"]
        refs = language_server.request_references("src/utils.lua", range_start["line"], range_start["character"])

        assert refs is not None
        assert isinstance(refs, list)
        # trim function appears in: usage (line 32 in main.lua)
        # Note: The declaration itself may or may not be included as a reference
        assert len(refs) >= 1, f"Should find at least 1 reference to utils.trim, found {len(refs)}"

        # Verify exact reference locations
        ref_files = {}
        for ref in refs:
            filename = ref.get("uri", "").split("/")[-1]
            if filename not in ref_files:
                ref_files[filename] = []
            ref_files[filename].append(ref["range"]["start"]["line"])

        # The declaration may or may not be included
        if "utils.lua" in ref_files:
            assert (
                5 in ref_files["utils.lua"]
            ), f"If declaration is included, it should be at line 6 (0-indexed: 5), found at {ref_files['utils.lua']}"

        # Check main.lua has usage
        assert "main.lua" in ref_files, "Should find trim usage in main.lua"
        assert (
            31 in ref_files["main.lua"]
        ), f"Should find trim usage at line 32 (0-indexed: 31) in main.lua, found at lines {ref_files.get('main.lua', [])}"

        # Check for cross-file references from main.lua
        main_refs = [ref for ref in refs if "main.lua" in ref.get("uri", "")]
        assert len(main_refs) > 0, "utils.trim should be called in main.lua"

    @pytest.mark.parametrize("language_server", [Language.LUA], indirect=True)
    def test_hover_information(self, language_server: SolidLanguageServer) -> None:
        """Test hover information for symbols."""
        # Get hover info for a function
        hover_info = language_server.request_hover("src/calculator.lua", 5, 10)  # Position near add function

        assert hover_info is not None, "Should provide hover information"

        # Hover info could be a dict with 'contents' or a string
        if isinstance(hover_info, dict):
            assert "contents" in hover_info or "value" in hover_info, "Hover should have contents"

    @pytest.mark.parametrize("language_server", [Language.LUA], indirect=True)
    def test_full_symbol_tree(self, language_server: SolidLanguageServer) -> None:
        """Test that full symbol tree is not empty."""
        symbols = language_server.request_full_symbol_tree()

        assert symbols is not None
        assert len(symbols) > 0, "Symbol tree should not be empty"

        # The tree should have at least one root node
        root = symbols[0]
        assert isinstance(root, dict), "Root should be a dict"
        assert "name" in root, "Root should have a name"

    @pytest.mark.parametrize("language_server", [Language.LUA], indirect=True)
    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").get_all_symbols_and_roots()

        assert test_symbols is not None
        assert len(test_symbols) > 0

        # The test file should have some content that references calculator
        symbol_list = test_symbols[0] if isinstance(test_symbols, tuple) else test_symbols
        assert len(symbol_list) > 0, "test_calculator.lua should have symbols"

```

--------------------------------------------------------------------------------
/src/solidlsp/language_servers/fortran_language_server.py:
--------------------------------------------------------------------------------

```python
"""
Fortran Language Server implementation using fortls.
"""

import logging
import os
import pathlib
import re
import shutil
import threading

from overrides import override

from solidlsp import ls_types
from solidlsp.ls import DocumentSymbols, LSPFileBuffer, SolidLanguageServer
from solidlsp.ls_config import LanguageServerConfig
from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams
from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo
from solidlsp.settings import SolidLSPSettings

log = logging.getLogger(__name__)


class FortranLanguageServer(SolidLanguageServer):
    """Fortran Language Server implementation using fortls."""

    @override
    def _get_wait_time_for_cross_file_referencing(self) -> float:
        return 3.0  # fortls needs time for workspace indexing

    @override
    def is_ignored_dirname(self, dirname: str) -> bool:
        # For Fortran projects, ignore common build directories
        return super().is_ignored_dirname(dirname) or dirname in [
            "build",
            "Build",
            "BUILD",
            "bin",
            "lib",
            "mod",  # Module files directory
            "obj",  # Object files directory
            ".cmake",
            "CMakeFiles",
        ]

    def _fix_fortls_selection_range(
        self, symbol: ls_types.UnifiedSymbolInformation, file_content: str
    ) -> ls_types.UnifiedSymbolInformation:
        """
        Fix fortls's incorrect selectionRange that points to line start instead of identifier name.

        fortls bug: selectionRange.start.character is 0 (line start) but should point to the
        function/subroutine/module/program name position. This breaks MCP server features that
        rely on the exact identifier position for finding references.

        Args:
            symbol: The symbol with potentially incorrect selectionRange
            file_content: Full file content to parse the line

        Returns:
            Symbol with corrected selectionRange pointing to the identifier name

        """
        if "selectionRange" not in symbol:
            return symbol

        sel_range = symbol["selectionRange"]
        start_line = sel_range["start"]["line"]
        start_char = sel_range["start"]["character"]

        # Split file content into lines
        lines = file_content.split("\n")
        if start_line >= len(lines):
            return symbol

        line = lines[start_line]

        # Fortran keywords that define named constructs
        # Match patterns:
        # Standard keywords: <keyword> <whitespace> <identifier_name>
        #   "    function add_numbers(a, b) result(sum)"  -> keyword="function", name="add_numbers"
        #   "subroutine print_result(value)"             -> keyword="subroutine", name="print_result"
        #   "module math_utils"                          -> keyword="module", name="math_utils"
        #   "program test_program"                       -> keyword="program", name="test_program"
        #   "interface distance"                         -> keyword="interface", name="distance"
        #
        # Type definitions (can have :: syntax):
        #   "type point"                                 -> keyword="type", name="point"
        #   "type :: point"                              -> keyword="type", name="point"
        #   "type, extends(base) :: derived"             -> keyword="type", name="derived"
        #
        # Submodules (have parent module in parentheses):
        #   "submodule (parent_mod) child_mod"           -> keyword="submodule", name="child_mod"

        # Try type pattern first (has complex syntax with optional comma and ::)
        type_pattern = r"^\s*type\s*(?:,.*?)?\s*(?:::)?\s*([a-zA-Z_]\w*)"
        match = re.match(type_pattern, line, re.IGNORECASE)

        if match:
            # For type pattern, identifier is in group 1
            identifier_name = match.group(1)
            identifier_start = match.start(1)
        else:
            # Try standard keywords pattern
            standard_pattern = r"^\s*(function|subroutine|module|program|interface)\s+([a-zA-Z_]\w*)"
            match = re.match(standard_pattern, line, re.IGNORECASE)

            if not match:
                # Try submodule pattern
                submodule_pattern = r"^\s*submodule\s*\([^)]+\)\s+([a-zA-Z_]\w*)"
                match = re.match(submodule_pattern, line, re.IGNORECASE)

                if match:
                    identifier_name = match.group(1)
                    identifier_start = match.start(1)
            else:
                identifier_name = match.group(2)
                identifier_start = match.start(2)

        if match:
            # Create corrected selectionRange
            new_sel_range = {
                "start": {"line": start_line, "character": identifier_start},
                "end": {"line": start_line, "character": identifier_start + len(identifier_name)},
            }

            # Create modified symbol with corrected selectionRange
            corrected_symbol = symbol.copy()
            corrected_symbol["selectionRange"] = new_sel_range  # type: ignore[typeddict-item]

            log.debug(f"Fixed fortls selectionRange for {identifier_name}: char {start_char} -> {identifier_start}")

            return corrected_symbol

        # If no match, return symbol unchanged (e.g., for variables, which don't have this pattern)
        return symbol

    @override
    def request_document_symbols(self, relative_file_path: str, file_buffer: LSPFileBuffer | None = None) -> DocumentSymbols:
        # Override to fix fortls's incorrect selectionRange bug.
        #
        # fortls returns selectionRange pointing to line start (character 0) instead of the
        # identifier name position. This breaks MCP server features that rely on exact positions.
        #
        # This override:
        # 1. Gets symbols from fortls via parent implementation
        # 2. Parses each symbol's line to find the correct identifier position
        # 3. Fixes selectionRange for all symbols recursively
        # 4. Returns corrected symbols

        # Get symbols from fortls (with incorrect selectionRange)
        document_symbols = super().request_document_symbols(relative_file_path, file_buffer=file_buffer)

        # Get file content for parsing
        with self.open_file(relative_file_path) as file_data:
            file_content = file_data.contents

        # Fix selectionRange recursively for all symbols
        def fix_symbol_and_children(symbol: ls_types.UnifiedSymbolInformation) -> ls_types.UnifiedSymbolInformation:
            # Fix this symbol's selectionRange
            fixed = self._fix_fortls_selection_range(symbol, file_content)

            # Fix children recursively
            if fixed.get("children"):
                fixed["children"] = [fix_symbol_and_children(child) for child in fixed["children"]]

            return fixed

        # Apply fix to all symbols
        fixed_root_symbols = [fix_symbol_and_children(sym) for sym in document_symbols.root_symbols]

        return DocumentSymbols(fixed_root_symbols)

    @staticmethod
    def _check_fortls_installation() -> str:
        """Check if fortls is available."""
        fortls_path = shutil.which("fortls")
        if fortls_path is None:
            raise RuntimeError("fortls is not installed or not in PATH.\nInstall it with: pip install fortls")
        return fortls_path

    def __init__(self, config: LanguageServerConfig, repository_root_path: str, solidlsp_settings: SolidLSPSettings):
        # Check fortls installation
        fortls_path = self._check_fortls_installation()

        # Command to start fortls language server
        # fortls uses stdio for LSP communication by default
        fortls_cmd = f"{fortls_path}"

        super().__init__(
            config, repository_root_path, ProcessLaunchInfo(cmd=fortls_cmd, cwd=repository_root_path), "fortran", solidlsp_settings
        )
        self.server_ready = threading.Event()

    @staticmethod
    def _get_initialize_params(repository_absolute_path: str) -> InitializeParams:
        """Initialize params for Fortran Language Server."""
        root_uri = pathlib.Path(repository_absolute_path).as_uri()
        initialize_params = {
            "locale": "en",
            "capabilities": {
                "textDocument": {
                    "synchronization": {"didSave": True, "dynamicRegistration": True},
                    "completion": {
                        "dynamicRegistration": True,
                        "completionItem": {
                            "snippetSupport": True,
                            "commitCharactersSupport": True,
                            "documentationFormat": ["markdown", "plaintext"],
                            "deprecatedSupport": True,
                            "preselectSupport": True,
                        },
                    },
                    "hover": {"dynamicRegistration": True, "contentFormat": ["markdown", "plaintext"]},
                    "definition": {"dynamicRegistration": True},
                    "references": {"dynamicRegistration": True},
                    "documentSymbol": {
                        "dynamicRegistration": True,
                        "hierarchicalDocumentSymbolSupport": True,
                        "symbolKind": {"valueSet": list(range(1, 27))},
                    },
                    "formatting": {"dynamicRegistration": True},
                    "rangeFormatting": {"dynamicRegistration": True},
                    "codeAction": {"dynamicRegistration": True},
                },
                "workspace": {
                    "workspaceFolders": True,
                    "didChangeConfiguration": {"dynamicRegistration": True},
                    "symbol": {
                        "dynamicRegistration": True,
                        "symbolKind": {"valueSet": list(range(1, 27))},
                    },
                },
            },
            "processId": os.getpid(),
            "rootPath": repository_absolute_path,
            "rootUri": root_uri,
            "workspaceFolders": [
                {
                    "uri": root_uri,
                    "name": os.path.basename(repository_absolute_path),
                }
            ],
        }
        return initialize_params  # type: ignore[return-value]

    def _start_server(self) -> None:
        """Start Fortran Language Server process."""

        def window_log_message(msg: dict) -> None:
            log.info(f"Fortran LSP: window/logMessage: {msg}")

        def do_nothing(params: dict) -> None:
            return

        def register_capability_handler(params: dict) -> None:
            return

        # Register LSP message handlers
        self.server.on_request("client/registerCapability", register_capability_handler)
        self.server.on_notification("window/logMessage", window_log_message)
        self.server.on_notification("$/progress", do_nothing)
        self.server.on_notification("textDocument/publishDiagnostics", do_nothing)

        log.info("Starting Fortran Language Server (fortls) process")
        self.server.start()

        initialize_params = self._get_initialize_params(self.repository_root_path)
        log.info("Sending initialize request to Fortran Language Server")

        init_response = self.server.send.initialize(initialize_params)

        # Verify server capabilities
        capabilities = init_response.get("capabilities", {})
        assert "textDocumentSync" in capabilities
        if "completionProvider" in capabilities:
            log.info("Fortran LSP completion provider available")
        if "definitionProvider" in capabilities:
            log.info("Fortran LSP definition provider available")
        if "referencesProvider" in capabilities:
            log.info("Fortran LSP references provider available")
        if "documentSymbolProvider" in capabilities:
            log.info("Fortran LSP document symbol provider available")

        self.server.notify.initialized({})
        self.completions_available.set()

        # Fortran Language Server is ready after initialization
        self.server_ready.set()
        log.info("Fortran Language Server initialization complete")

```

--------------------------------------------------------------------------------
/test/solidlsp/swift/test_swift_basic.py:
--------------------------------------------------------------------------------

```python
"""
Basic integration tests for the Swift language server functionality.

These tests validate the functionality of the language server APIs
like request_references using the Swift test repository.
"""

import os
import platform

import pytest

from serena.project import Project
from serena.text_utils import LineType
from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language

# Skip Swift tests on Windows due to complex GitHub Actions configuration
WINDOWS_SKIP = platform.system() == "Windows"
WINDOWS_SKIP_REASON = "GitHub Actions configuration for Swift on Windows is complex, skipping for now."

pytestmark = [pytest.mark.swift, pytest.mark.skipif(WINDOWS_SKIP, reason=WINDOWS_SKIP_REASON)]


class TestSwiftLanguageServerBasics:
    """Test basic functionality of the Swift language server."""

    @pytest.mark.parametrize("language_server", [Language.SWIFT], indirect=True)
    def test_goto_definition_calculator_class(self, language_server: SolidLanguageServer) -> None:
        """Test goto_definition on Calculator class usage."""
        file_path = os.path.join("src", "main.swift")

        # Find the Calculator usage at line 5: let calculator = Calculator()
        # Position should be at the "Calculator()" call
        definitions = language_server.request_definition(file_path, 4, 23)  # Position at Calculator() call
        assert isinstance(definitions, list), "Definitions should be a list"
        assert len(definitions) > 0, "Should find definition for Calculator class"

        # Verify the definition points to the Calculator class definition
        calculator_def = definitions[0]
        assert calculator_def.get("uri", "").endswith("main.swift"), "Definition should be in main.swift"

        # The Calculator class is defined starting at line 16
        start_line = calculator_def.get("range", {}).get("start", {}).get("line")
        assert start_line == 15, f"Calculator class definition should be at line 16, got {start_line + 1}"

    @pytest.mark.parametrize("language_server", [Language.SWIFT], indirect=True)
    def test_goto_definition_user_struct(self, language_server: SolidLanguageServer) -> None:
        """Test goto_definition on User struct usage."""
        file_path = os.path.join("src", "main.swift")

        # Find the User usage at line 9: let user = User(name: "Alice", age: 30)
        # Position should be at the "User(...)" call
        definitions = language_server.request_definition(file_path, 8, 18)  # Position at User(...) call
        assert isinstance(definitions, list), "Definitions should be a list"
        assert len(definitions) > 0, "Should find definition for User struct"

        # Verify the definition points to the User struct definition
        user_def = definitions[0]
        assert user_def.get("uri", "").endswith("main.swift"), "Definition should be in main.swift"

        # The User struct is defined starting at line 26
        start_line = user_def.get("range", {}).get("start", {}).get("line")
        assert start_line == 25, f"User struct definition should be at line 26, got {start_line + 1}"

    @pytest.mark.parametrize("language_server", [Language.SWIFT], indirect=True)
    def test_goto_definition_calculator_method(self, language_server: SolidLanguageServer) -> None:
        """Test goto_definition on Calculator method usage."""
        file_path = os.path.join("src", "main.swift")

        # Find the add method usage at line 6: let result = calculator.add(5, 3)
        # Position should be at the "add" method call
        definitions = language_server.request_definition(file_path, 5, 28)  # Position at add method call
        assert isinstance(definitions, list), "Definitions should be a list"

        # Verify the definition points to the add method definition
        add_def = definitions[0]
        assert add_def.get("uri", "").endswith("main.swift"), "Definition should be in main.swift"

        # The add method is defined starting at line 17
        start_line = add_def.get("range", {}).get("start", {}).get("line")
        assert start_line == 16, f"add method definition should be at line 17, got {start_line + 1}"

    @pytest.mark.parametrize("language_server", [Language.SWIFT], indirect=True)
    def test_goto_definition_cross_file(self, language_server: SolidLanguageServer) -> None:
        """Test goto_definition across files - Utils struct."""
        utils_file = os.path.join("src", "utils.swift")

        # 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).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"]
        definitions = language_server.request_definition(utils_file, sel_start["line"], sel_start["character"])
        assert isinstance(definitions, list), "Definitions should be a list"

        # Should find the Utils struct definition itself
        utils_def = definitions[0]
        assert utils_def.get("uri", "").endswith("utils.swift"), "Definition should be in utils.swift"

    @pytest.mark.parametrize("language_server", [Language.SWIFT], indirect=True)
    def test_request_references_calculator_class(self, language_server: SolidLanguageServer) -> None:
        """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).get_all_symbols_and_roots()

        calculator_symbol = next((s for s in symbols[0] if s.get("name") == "Calculator"), None)

        sel_start = calculator_symbol["selectionRange"]["start"]
        references = language_server.request_references(file_path, sel_start["line"], sel_start["character"])
        assert isinstance(references, list), "References should be a list"
        assert len(references) > 0, "Calculator class should be referenced"

        # Validate that Calculator is referenced in the main function
        calculator_refs = [ref for ref in references if ref.get("uri", "").endswith("main.swift")]
        assert len(calculator_refs) > 0, "Calculator class should be referenced in main.swift"

        # Check that one reference is at line 5 (let calculator = Calculator())
        line_5_refs = [ref for ref in calculator_refs if ref.get("range", {}).get("start", {}).get("line") == 4]
        assert len(line_5_refs) > 0, "Calculator should be referenced at line 5"

    @pytest.mark.parametrize("language_server", [Language.SWIFT], indirect=True)
    def test_request_references_user_struct(self, language_server: SolidLanguageServer) -> None:
        """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).get_all_symbols_and_roots()

        user_symbol = next((s for s in symbols[0] if s.get("name") == "User"), None)

        sel_start = user_symbol["selectionRange"]["start"]
        references = language_server.request_references(file_path, sel_start["line"], sel_start["character"])
        assert isinstance(references, list), "References should be a list"

        # Validate that User is referenced in the main function
        user_refs = [ref for ref in references if ref.get("uri", "").endswith("main.swift")]
        assert len(user_refs) > 0, "User struct should be referenced in main.swift"

        # Check that one reference is at line 9 (let user = User(...))
        line_9_refs = [ref for ref in user_refs if ref.get("range", {}).get("start", {}).get("line") == 8]
        assert len(line_9_refs) > 0, "User should be referenced at line 9"

    @pytest.mark.parametrize("language_server", [Language.SWIFT], indirect=True)
    def test_request_references_utils_struct(self, language_server: SolidLanguageServer) -> None:
        """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).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")
        sel_start = utils_symbol["selectionRange"]["start"]
        references = language_server.request_references(file_path, sel_start["line"], sel_start["character"])
        assert isinstance(references, list), "References should be a list"
        assert len(references) > 0, "Utils struct should be referenced"

        # Validate that Utils is referenced in main.swift
        utils_refs = [ref for ref in references if ref.get("uri", "").endswith("main.swift")]
        assert len(utils_refs) > 0, "Utils struct should be referenced in main.swift"

        # Check that one reference is at line 12 (Utils.calculateArea call)
        line_12_refs = [ref for ref in utils_refs if ref.get("range", {}).get("start", {}).get("line") == 11]
        assert len(line_12_refs) > 0, "Utils should be referenced at line 12"


class TestSwiftProjectBasics:
    @pytest.mark.parametrize("project", [Language.SWIFT], indirect=True)
    def test_retrieve_content_around_line(self, project: Project) -> None:
        """Test retrieve_content_around_line functionality with various scenarios."""
        file_path = os.path.join("src", "main.swift")

        # Scenario 1: Find Calculator class definition
        calculator_line = None
        for line_num in range(1, 50):  # Search first 50 lines
            try:
                line_content = project.retrieve_content_around_line(file_path, line_num)
                if line_content.lines and "class Calculator" in line_content.lines[0].line_content:
                    calculator_line = line_num
                    break
            except:
                continue

        assert calculator_line is not None, "Calculator class not found"
        line_calc = project.retrieve_content_around_line(file_path, calculator_line)
        assert len(line_calc.lines) == 1
        assert "class Calculator" in line_calc.lines[0].line_content
        assert line_calc.lines[0].line_number == calculator_line
        assert line_calc.lines[0].match_type == LineType.MATCH

        # Scenario 2: Context above and below Calculator class
        with_context_around_calculator = project.retrieve_content_around_line(file_path, calculator_line, 2, 2)
        assert len(with_context_around_calculator.lines) == 5
        assert "class Calculator" in with_context_around_calculator.matched_lines[0].line_content
        assert with_context_around_calculator.num_matched_lines == 1

        # Scenario 3: Search for struct definitions
        struct_pattern = r"struct\s+\w+"
        matches = project.search_source_files_for_pattern(struct_pattern)
        assert len(matches) > 0, "Should find struct definitions"
        # Should find User struct
        user_matches = [m for m in matches if "User" in str(m)]
        assert len(user_matches) > 0, "Should find User struct"

        # Scenario 4: Search for class definitions
        class_pattern = r"class\s+\w+"
        matches = project.search_source_files_for_pattern(class_pattern)
        assert len(matches) > 0, "Should find class definitions"
        # Should find Calculator and Circle classes
        calculator_matches = [m for m in matches if "Calculator" in str(m)]
        circle_matches = [m for m in matches if "Circle" in str(m)]
        assert len(calculator_matches) > 0, "Should find Calculator class"
        assert len(circle_matches) > 0, "Should find Circle class"

        # Scenario 5: Search for enum definitions
        enum_pattern = r"enum\s+\w+"
        matches = project.search_source_files_for_pattern(enum_pattern)
        assert len(matches) > 0, "Should find enum definitions"
        # Should find Status enum
        status_matches = [m for m in matches if "Status" in str(m)]
        assert len(status_matches) > 0, "Should find Status enum"

```
Page 5/17FirstPrevNextLast