345 Commits
Author SHA1 Message Date
Ben KeilandCopilot b83b655ced fix: zip extract permission bits (#2102)
* Restore Unix executable bits when extracting zip archives

- SafeZipExtractor._extract_member now chmods each extracted file with the
  Unix mode stored in ZipInfo.external_attr (POSIX only, no-op when the
  archive carries no Unix attributes, e.g. Windows-authored zips).
- stdlib zipfile never restores permission bits itself; a fix is tracked
  upstream at https://github.com/python/cpython/pull/150061.
- Fixes archives with more than one executable losing their exec bit after
  extraction, e.g. the bundled JBR inside the Kotlin Language Server
  distribution (jbr/bin/java and native libs), which previously only had
  its single top-level launcher script chmod'd by the language-server code.

Fixes oraios/serena#2100

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-23 17:47:53 +02:00
sxhandsxh313 637ab7b7ee Fix AL language server lookup in newer extension layouts (#2087)
The AL adapter built a single executable path with a platform-specific
subdirectory (`bin/win32/...` on Windows) and raised "executable not found"
when it was absent. Compare the two VSIX packages from the marketplace with
the URL the adapter itself uses:

  18.0.2242655 (Serena's pinned version): bin/{win32,linux,darwin}/<host>
  18.0.2732683 (the build reported in #2069):  bin/<host>, no platform subdirectories

decision(al): probe both layouts instead of making the path configurable, since the
  extension build Serena downloads and the one the user has in VS Code differ by design.
constraint(al): keep the platform subdirectory first so existing behaviour is unchanged
  for the pinned version; only a missing executable falls through.
learned(al): neither VSIX declares a targetPlatform, yet the newer package contains no unix or
  darwin binaries at all; why Microsoft changed the packaging is upstream of this fix.

The error message now lists every candidate it tried, so the next layout change upstream is
identifiable from the failure alone rather than by reading the adapter.

Fixes #2069

Co-authored-by: sxh313 <sxh313@users.noreply.github.com>
2026-09-23 15:43:28 +02:00
Aleksei Tcelishchev 15502cee56 feat(solidlsp): add Astro language server support (#2085)
* feat(solidlsp): add Astro language server support (T170)

* test(solidlsp): fix relative_paths type extraction in test_astro_basic

* refactor(solidlsp): replace asserts with explicit exceptions in Astro LSP

* docs(memories): document rule against assert in language server guide

* docs: add Astro language server documentation (README, docs, template, CHANGELOG)

* feat(solidlsp): implement dual-server architecture for Astro with companion TypeScript server (#2085)

- Implement companion AstroTypeScriptServer using @astrojs/ts-plugin for cross-file code intelligence between .ts and .astro components
- Route .ts/.js document symbols, definitions, references, and renames through companion TypeScript server
- Support two-way buffer edit forwarding between Astro LS and companion TS server
- Replace all assert statements with explicit SolidLSPException and FileNotFoundError
- Handle *.customData configuration requests for Volar HTML service
- Register .astro extension in src/serena/hooks.py
- Add test fixtures and tests for symbol retrieval and cross-file references from TypeScript to Astro components
- Update documentation and CHANGELOG

* fix(solidlsp): narrow astro_ls type to AstroLanguageServer in companion server test

* fix(solidlsp): prevent caching empty document symbols and poll initial compilation in Nextflow tests
2026-09-23 15:38:19 +02:00
Amir Fathi a4dff9e0fc fix(typescript): prefer the src subtree over an adjacent tool config when warming up an additional workspace (#2097)
TypeScriptLanguageServer._find_representative_source_file scanned files directly
adjacent to tsconfig.json before checking a src/ subdirectory, so a same-level tool
config that the tsconfig excludes (vitest.config.ts, jest.config.ts, etc.) could be
picked as the file used to trigger project activation for an additional workspace
folder. The wrong inferred TypeScript project then loads, and cross-package
find_referencing_symbols queries silently return {} instead of raising or warning.

Reorder the scan to walk the src/ subtree first (recursively, respecting the usual
ignored-directory rules) and only fall back to a same-level file when no src/
directory exists, matching the fallback the reporter's issue proposed.

Fixes #2090

Signed-off-by: Amir Fathi <amirfathi.me@gmail.com>
2026-09-23 15:18:05 +02:00
Amir Fathi cf54869af8 fix(typescript): drain in-flight indexing on later cross-file queries (#1978)
_wait_for_cross_file_references_if_needed latched after the first cross-file
query and never waited again, even when a later query opened a file from a
project tsserver had not loaded yet and started a fresh $/progress cycle.
find_referencing_symbols and find_references would then return whatever
tsserver had indexed so far, silently partial, with nothing distinguishing it
from a complete answer.

The latch still covers the first query's start-grace wait unchanged. A later
query now also checks whether a progress token is currently active and, if
so, waits for it to drain before returning.

Fixes #1937
2026-09-23 15:09:02 +02:00
Dominik Jain fba55b6844 Merge remote-tracking branch 'origin/main' into perf/search-text-line-lookup-pr
Conflicts:
  src/serena/util/text_utils.py
2026-09-23 14:07:36 +02:00
Dominik Jain 26939c447f Refactoring: Improve class naming and consolidate text coordinate representations
* Rename TextCoordinates -> TextCoordinateProvider
* Consolidate ls_util.LineCol, text_utils.TextCoords -> ls_util.TextCoordinates
2026-09-23 14:03:42 +02:00
Guillermo fa79a2260f * perf(search_text): precompute line offsets for O(log n) line lookup
search_for_pattern resolved each match's line number by rescanning the
file from the beginning (TextUtils.get_line_from_index walks a
TextStepper from index 0), making coordinate resolution O(n) per match
and O(n*m) for m matches. search_text now precomputes line start
offsets once per file (O(n)) and resolves each match via binary search
(O(log n) per match).

The precomputed table mirrors TextStepper line semantics exactly:
\n, \r\n and bare \r are line separators, and an index pointing at the
\n of a \r\n pair resolves to (next line, 0) — the same rule
TextUtils.get_line_col_from_index implements, now pinned by regression
tests (including the mixed line-ending edge cases from the
insert_text_at_position fix).

On a synthetic 12k-line file (494 KB) with 723 matches, match-coordinate
resolution drops from ~1764 ms to ~2 ms (~1000x); the one-off
precompute costs ~1.1 ms. Small files regress nothing (100 lines, 5
matches: 70 µs -> 11 µs). Results are byte-for-byte identical to the
previous implementation.

Note: compatible with PR #1899 (interruptible agent regexes): that PR
touches the re.compile call site in search_text and the ContentReplacer
helpers, this PR touches the post-match line-coordinate resolution; the
two changes are complementary and rebase cleanly onto each other.

* perf(search_text): add reproducible benchmark script

scripts/profile_search_text.py regenerates the synthetic benchmark
content with a fixed seed (no real-world code), asserts both resolution
paths produce identical results, and prints the before/after timings
quoted in the PR description. Default: 12k lines / ~1830 matches;
optional CLI args scale the file down for quick runs.

* refactor(ls): encapsulate cached text coordinates in TextCoordinates abstraction

Address review feedback on the search_text line-lookup PR: the previously
added module-level helpers duplicated TextStepper's line-ending logic and
exposed raw offsets as a low-level data structure shared between two
functions, violating the project's software design principles (each
concern in exactly one home; dataclasses instead of tuples for simple
data storage).

Introduce in solidlsp/ls_utils.py:

- LineCol: frozen, kw-only dataclass for a 0-based line/column position
- TextCoordinates: encapsulates the cached table of line start offsets,
  built via TextStepper (step_line + line_start_idx), with a single
  public method line_col_at_index() resolving an index via binary
  search, including the CRLF rule (an index pointing at the '\n' of a
  '\r\n' pair denotes the beginning of the next line, column 0) and
  InvalidTextLocationError for out-of-range indices

search_text now instantiates TextCoordinates once per file and resolves
each match's coordinates through the public method; the private helpers
(_compute_line_starts, _line_col_at_index) are removed.

Equivalence with TextUtils.get_line_col_from_index verified across
mixed line endings, empty content and boundary indices (0 mismatches).

Tests are behaviour-anchored: the implementation-coupled parametrized
test importing the private helpers is replaced by public-contract tests
of TextCoordinates (test/solidlsp/test_ls_utils.py) and absolute line
assertions through the public search_text API. The benchmark script
uses the public API as well.

Benchmark (synthetic 12k lines, ~723 matches, best of 5): coordinate
resolution ~1764 ms -> ~2 ms; precompute ~1.1 ms; small files unchanged.

Semantics are unchanged; results are identical to the previously
proposed implementation and to the upstream reference implementation.

* fix(test): rename test_ls_utils to test_text_coordinates to avoid basename collision

The new test file collided with the pre-existing upstream
test/solidlsp/util/test_ls_utils.py: pytest (prepend import mode, no
__init__.py in the test dirs) requires unique basenames, and collecting
both modules produced an import-file-mismatch error that aborted
collection with exit code 2 across every CI matrix job.

Rename to test_text_coordinates.py (unique, and matches the class under
test). Full-suite collection verified locally (2252 tests, 0 errors).
2026-09-23 14:03:08 +02:00
Max 9f19a79a04 fix(dart): omit rootUri/rootPath (#2045) (#2051)
The Dart analysis server treats rootUri as an additional analysis root on top of
workspaceFolders, with no de-duplication, so on a monorepo root the whole tree is
analysed and the server burns CPU at idle. Always omit rootUri/rootPath and rely on
workspaceFolders alone.
2026-09-21 21:57:33 +02:00
Amir Fathi 941f4ded18 fix(csharp): stop tuple-typed properties losing their name to the method branch (#1967)
* fix(csharp): stop tuple-typed properties losing their name to the method branch

_extract_base_name_and_type split Roslyn's "Name : Type" property names by
checking for a literal '(' anywhere in the raw string. A C# tuple type is
written with parentheses ("(int X, string Y)"), so a tuple-typed property
tripped that guard and fell into the method branch instead, which kept the
trailing " :" as part of the reported name (e.g. "Position :"). Since
find_symbol defaults to exact name-path matching, such a property becomes
unfindable by its real name.

The guard now only checks for '(' in the identifier segment before the
first " : ", not the whole string, so a parenthesis inside the type
annotation no longer affects branch selection.

* fix(csharp): bump the high-level symbol cache fingerprint

_normalize_symbol_name's output changed in this PR, and
_document_symbols_cache_fingerprint gates the cache that stores its
result; leaving the version at 1 would keep serving the old, corrupted
names to anyone with an existing on-disk cache.
2026-09-21 12:14:38 +02:00
kronosandClaude Sonnet 5 fba5258294 fix(kotlin): update managed Kotlin LSP to 263.4702.0
The previous default, 262.9593.0, is a JetBrains EAP-style build that has
expired: intellij-server exits at startup with "This build of intellij-server
has expired", so every Kotlin symbolic tool fails. 263.4702.0 is the newest
release on Kotlin/kotlin-lsp and starts normally.

Uses the same archive layout and CDN path as 262.9593.0. Hashes regenerated
with scripts/update_downloaded_dependency_hashes.py.

Fixes #2008

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 12:12:28 +02:00
Dominik Jain 3ad4044c69 Enable ty rule 'unresolved-attribute' for test/ 2026-09-18 13:08:36 +02:00
Dr. Dominik Jain 84c673bae4 Merge pull request #2035 from oraios/dev-v2
Add REPL (milestone for Serena v2)
2026-09-17 21:32:08 +02:00
Dominik Jain 6507092288 Mark R cross-file tests as flaky #1040 2026-09-17 21:07:47 +02:00
Amir Fathi 0b2e22bbca Fix: Compensate for incorrect body end coordinates in Godot LS (#1974)
Godot's GDScript parser can report a symbol's end column one column past the
line-end convention every other language server follows (closing a node's range from
the next lookahead token instead of the last consumed one, when that lookahead is a
synthesized newline); `replace_symbol_body` on the last function in a file silently
consumed the separating blank line as a result. `GodotLanguageServer` now corrects this
specific, measured overshoot when building its high-level document symbols (#1974)

---------

Signed-off-by: Amir Fathi <amirfathi.me@gmail.com>
2026-09-17 10:37:04 +02:00
Dr. Dominik Jain 403ad0a562 Merge pull request #1988 from oraios/ls-registry
SolidLSP: Add language server registry, supporting externally provided implementations
2026-09-12 23:16:52 +02:00
Dominik Jain 283140e7ae Refactor external language server registration
* Apply object-oriented design
* Establish common interface via protocol LanguageServerIdLike
* Move all registration concerns to LanguageServerRegistry
2026-09-12 15:15:34 +02:00
GuddXzyandGuddXzy 2d2e87763a fix: disable automatic type acquisition in TypeScript backends (#1990)
* fix: disable automatic type acquisition in TypeScript backends

* fix: use shared initialization builder for VTS

Follow review guidance to apply shallow per-key overrides without restoring the ATA default after a user replaces the typescript block. Preserve the legacy settings alias, document the behavior, and cover canonical-key precedence.

---------

Co-authored-by: GuddXzy <267062192+GuddXzy@users.noreply.github.com>
2026-09-08 11:17:35 +02:00
Dominik Jain 9f9db76622 Fix document symbol caching for language servers that post-process symbols
Caching happened in the base implementation before subclass overrides could
post-process the result, so an override's work was either never cached or,
if it mutated in place, re-applied to cached output on every hit.

Restructure both symbol caches so that they wrap the subclass logic:
subclasses now post-process via dedicated hooks (`_request_raw_document_symbols`
and `_build_document_symbols_from_raw_symbols`), and the cached value is
the fully processed result. Cache versions are bumped where the cached
content changes as a consequence.
2026-09-06 13:51:53 +02:00
Amir Fathi be609b6257 fix(kotlin): give concurrent Serena instances independent LSP storage
Two Serena instances activating the same project concurrently launched
their Kotlin LSP processes against the same on-disk index storage
location (both the modern launcher's --system-path arg and the legacy
initializationOptions.storagePath, hardcoded to None), so the second
instance's requests were repeatedly cancelled by the first instance's
server.

DependencyProvider now claims that storage directory with a
non-blocking file lock held for the process's lifetime. A single
instance, including across restarts, still gets the same directory
and keeps its cache; a second concurrent instance falls back to a
directory of its own instead of contending for the first one's.

Fixes #1966
2026-09-06 11:50:21 +02:00
Vitaly Ruhl 6000f16680 feat(solidlsp): prototype registrable language server adapters 2026-09-05 12:36:53 +02:00
xor 13ac8c5b1d SolidLSP: correct the position returned by insert_text_at_position (#1842)
insert_text_at_position returns the position of the end of the inserted text.
That position was computed by _get_updated_position_from_line_and_column_and_edit,
which steps the inserted text in isolation and adds the resulting line/column
delta to the start position.

An insertion is not independent of its surroundings. Under the LSP newline
definition adopted in 9208a3ae, a "\n" inserted directly after an existing "\r"
merges with it into a single "\r\n" sequence, so the text gains no line while the
isolated arithmetic still counts one:

    insert_text_at_position("\r", 1, 0, "\n")    -> ("\r\n", 2, 0); actual (1, 0)
    insert_text_at_position("x\ry", 1, 0, "\n")  -> ("x\r\ny", 2, 0); actual (1, 0)
    insert_text_at_position("a\r", 2, 0, "X")    -> ("a\r\nX", 2, 1); actual (1, 1)

The third case reaches the same fault through the one-line-past-EOF branch, which
prepends a "\n" that then merges with the trailing "\r". The converse interaction
was wrong too: inserting between the "\r" and the "\n" of a "\r\n" splits it, and
the isolated arithmetic reported (0, 2) -- a column on a line the split had just
emptied. In every case the resulting text was correct; only the position was wrong.

9208a3ae centralised line/column computation on TextStepper and reimplemented the
TextUtils methods on it. This helper was rebased onto TextStepper in that commit
but kept its original shape: it steps one string, and the string it steps is the
insertion rather than the result. Once a newline can be formed by two adjacent
characters, no computation over the inserted text alone can be correct.

The position is now determined from the resulting text via get_line_col_from_index,
the same function that resolves positions everywhere else, which removes the last
computation in TextUtils that did not go through the centralised path. The helper
had no other callers and is deleted, along with the line/col adjustment in the
past-EOF branch that existed only to feed it.

The column is clamped to the end of the text before both the splice and the
derivation. This is not a new tolerance: the splice already clamped implicitly
(text[:i] with i > len(text) yields the whole text), so an out-of-range column has
always appended successfully. Making the clamp explicit keeps the position derived
from the same index the splice used; without it, deriving from the result would
newly raise for input that previously worked.

Columns are offsets into the Python string (code points), which the docstring now
states. LSP columns are UTF-16 code units and nothing converts between the two at
the boundary -- a real defect, but a pre-existing and separate one: the previous
arithmetic did not preserve UTF-16 units either, since it added a code-point length
to a code-unit column and so produced a value in neither unit.

    "\U0001f600" + "\U0001f600" at column 2
        old (0, 3); UTF-16 (0, 4); code points (0, 2)

Seven regression tests cover the boundary, mid-document and past-EOF merges, the
newline split, an out-of-range column, a column past a non-BMP character, and an
unaffected "\n"-terminated control. The six that pin changed behaviour were each
verified to fail before the change; the control passes either way.
2026-09-04 13:09:55 +02:00
Scott McLeod bcb3fc74ff Detect FreeBSD as a platform (#1947)
Language server initialization failed on FreeBSD with "Unknown platform" as there was no mapping for FreeBSD.
2026-09-03 17:15:10 +02:00
MaxandYu-0312 24940a1560 fix(process): reap language server descendants (#1918)
* fix(process): reap language server descendants

* fix(process): preserve descendant snapshot for kill fallback

* fix(process): share termination timeout deadline

* fix(process): reap descendants in process-group cleanup

* fix(process): reap leader after descendant kill timeout

---------

Co-authored-by: Yu-0312 <2.66498311e+08+Yu-0312@users.noreply.github.com>
2026-09-03 15:28:05 +02:00
MaxandYu-0312 6f86ae308e fix(solidity): isolate Hardhat state on macOS (#1910)
* fix(solidity): isolate Hardhat state on macOS

---------

Co-authored-by: Yu-0312 <2.66498311e+08+Yu-0312@users.noreply.github.com>
2026-09-03 15:21:15 +02:00
Johan Larsson 25631db556 feat(solidlsp): add Fatou support
Refs #1931
2026-09-03 14:43:25 +02:00
Amir Fathi e1322a3b99 fix(dart): wait for analyzer readiness signal before returning from start()
DartLanguageServer registered handlers for $/analyzerStatus and
experimental/serverStatus but both were no-ops, so start() returned as
soon as initialized was sent instead of waiting for either signal, unlike
every other backend (pyright, basedpyright, rust-analyzer, clojure-lsp,
jedi, omnisharp, clangd) that receives the same notifications. A request
issued right after activation could return before the workspace scan
finished.

Gate on a threading.Event set by either notification, bounded by 60s,
mirroring pyright_server.py's analysis_complete pattern.
2026-09-03 13:02:50 +02:00
Dr. Dominik Jain f41f33c904 Merge branch 'main' into fix/1871-nextflow-scan-flush-flag 2026-09-02 13:06:49 +02:00
Amir Fathi dc59a8931c Fix: Exceptions raised during LanguageServerManager.start did not stop the language server subprocess if it was already started
start() now catches an exception from _start_server(), stops the process if it is
already running, and re-raises. 

Fixes #1949
2026-09-02 12:53:41 +02:00
Michael Panchenko 7fcbca7e62 Merge pull request #1848 from AmirF194/fix/1814-tsserver-crash-silent-empty-result
Fix: surface a mid-indexing tsserver crash instead of returning {}
2026-08-20 08:51:14 +02:00
aayushbaluni d4dbcecaae fix(clojure): declare didChangeWatchedFiles client capability
Serena notifies language servers about files changed outside its own edit tools (a git checkout, another editor, a build step) by sending workspace/didChangeWatchedFiles from LanguageServerManager.poll_and_notify, whose docstring names this exact case: such edits are 'otherwise invisible to a warm language server, causing symbolic queries to answer from a stale index'.

ClojureLSP never declared the corresponding client capability, so clojure-lsp was not told those notifications are sent and need not treat them as a reason to invalidate its analysis. DefaultInitializeParamsBuilder does not supply a default capabilities block, so nothing filled this in on the server's behalf.

Relates to #1593, where find_symbol returned a body from a comment mentioning the symbol rather than its definition, at a position the symbol had previously occupied.
2026-08-17 11:39:28 +05:30
Amir Fathi c72c07ae29 fix(nextflow): don't mark workspace scan flushed when both probes fail
_flush_deferred_workspace_scan sets _workspace_scan_flushed unconditionally after its
two completion() flush attempts, even when both raised. A later find_referencing_symbols
call then silently skips the flush and answers from a possibly-incomplete workspace AST
cache for the rest of the session, with no exception and no retry.

Fixes #1871
2026-08-15 19:05:13 +00:00
Jia Tianzhao 27644053ad fix(dart): handle analyzer status notifications (#1863)
The Dart analysis server emits $/analyzerStatus while it analyzes a workspace.
The Dart adapter did not register this server-specific notification, so the
generic notification dispatcher logged every event as an unhandled-method
warning even though no client action is required.

Register the method with the adapter's existing no-op notification handler,
keeping the global behavior for genuinely unknown notifications unchanged. Add
a startup regression test that sends the notification through the production
dispatcher, and document the fix in the changelog.

Fixes #1855
2026-08-13 22:39:50 +02:00
Amir Fathi ffcb66ba43 Fix: surface a mid-indexing tsserver crash instead of returning {}
typescript-language-server sends a $/progress "end" for the in-flight
token as part of tearing its connection down after tsserver aborts (e.g.
a V8 heap OOM). _wait_for_indexing_start_or_completion could not
distinguish that from a real completion, so find_referencing_symbols
logged "TypeScript cross-file indexing complete" and returned {} with
isError: false, indistinguishable from a symbol genuinely having no
references.

The crash is already observed independently via window/logMessage
(type Error, "[tsserver] Exited"), but the handler only logged it. Wire
that signal into a _crash_message flag and raise TypeScriptServerCrashedError
from every path that would otherwise report indexing as complete
(wait_for_indexing and both early-return branches of
_wait_for_indexing_start_or_completion), so a crash propagates as a tool
error instead of a silent empty result.

Fixes #1814
2026-08-13 12:18:34 +00:00
Merlin Hughes a9f99c679b Scala: wait for Metals' reported work, not a fixed 5 seconds (#1859)
Cross-file queries waited 5s after the first file was opened. On a cold Metals
that is long before it has imported the build, indexed, and — crucially —
compiled: references come from SemanticDB, which the build server writes as it
compiles, so a query made in between returns some of the references rather than
none, with nothing to mark it partial. Against a ~700-file Scala 3 build the
first find-references returned 124 of 242.

Metals already reports all of this as work-done progress; Serena did not declare
`window.workDoneProgress`, so none of it arrived. Declare it, track the tokens,
and wait for them before the first cross-file query — the same event-based shape
as TypeScript's indexing wait (#1639), whose hooks this uses.

Readiness is "nothing outstanding for a moment", not "nothing outstanding":
Metals hands off between its phases rather than overlapping them, so the token
set empties for around a second between the import ending and indexing starting,
and a plain drain returns in that gap. Measured on the same build, the first
find-references now returns all 242, taking 32s rather than 22s.
2026-08-13 11:43:24 +02:00
Dr. Dominik Jain 3c8e9854f6 Improve identification of container/low-level symbols (#1834)
This affects results returned for request_containing_symbol,
some tests were adjusted accordingly.
2026-08-09 20:12:51 +02:00
Dr. Dominik Jain 281e9db2eb Merge pull request #1823 from AmirF194/fix/1818-process-group-cleanup-without-enumeration 2026-08-09 17:37:16 +02:00
xor c9f0ab80f1 SolidLSP: admit Struct, Interface and Constant symbols as reference containers (#1831)
find_referencing_symbols degraded to file-level attribution for any
reference located inside a Go struct body, interface body or const
group: request_containing_symbol found no admissible container, so
request_referencing_symbols logged "Could not find containing symbol
... Returning file symbol instead" and fell back to the file symbol,
losing the answer the tool exists to give.

Root cause: the candidate-container filter admitted only Python's
container kinds {Method, Function, Class} (plus Variable via the
one-liner-exempt path). The language server is not at fault:
hierarchicalDocumentSymbolSupport is declared and the DocumentSymbol
tree is complete, but Go structs arrive as SymbolKind.Struct,
interfaces as Interface and const-group members as Constant - none of
which were admitted, so every candidate was rejected.

Fix, mirroring the existing structure of the filter:
- Struct and Interface join the multi-line container whitelist,
- Constant joins Variable on the one-liner-exempt path (const-group
  members are one-liners by nature, exactly like the module-level
  variables that path already serves).

The Python suite shows no attribution change
(test/solidlsp/python/test_symbol_retrieval.py: 80 passed). Languages
whose containers use the added kinds (e.g. Rust and C structs,
TypeScript interfaces) get the same admission; verified for Go and
Python only.

Regression coverage: new Go fixture containment_sample.go with a
const-iota group, a struct field and an interface method all
referencing a named type; four tests assert containing-symbol and
referencing-symbol attribution, and all four fail against the
pre-change ls.py (verified). Full go-marker suite: 21 passed,
1 skipped.
2026-08-09 16:07:20 +02:00
Amir Fathi ec18c48202 Fix: LSP process-group cleanup no longer requires process-table enumeration
An independently-started LSP process is already its own POSIX process group leader
(start_new_session=True), so cleanup can signal that known group directly via os.killpg
instead of walking the tree with psutil.Process.children(recursive=True), which requires
system-wide process-table enumeration that can be denied even for processes we started
and own (#1818).
2026-08-09 12:13:14 +00:00
1b459899ca Add Wolfram Language support via official LSPServer paclet (#1108)
Adds support for Wolfram Language (.wl, .wls files) using the official
WolframResearch LSPServer paclet, which communicates via stdio.
Requires Wolfram Mathematica 13.0+ or Wolfram Engine 12.1+.
The WolframKernel is located via WOLFRAM_PATH, the system PATH, common
install locations, or ls_path in ls_specific_settings.

Includes language server implementation, test repo, test suite
(skipped gracefully when WolframKernel is unavailable), and
documentation updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-09 13:31:30 +02:00
Evangelos KaratzasandClaude Opus 5 8ebb247dae Force the Nextflow server's deferred workspace scan before finding references (#1832)
The Nextflow language server does not scan the workspace when it says it does.
`LanguageService.initialize` -- which the "Initializing" progress notification we
wait for wraps -- only marks the workspace as unscanned and clears the AST cache.
The scan itself happens in `LanguageService.update0`, behind a 1s debounce, and
only on a round that finds no pending file change; a round that does find one
re-defers it via `updateLater`. The first `didOpen` of a session therefore pushes
the scan out by at least one further round, so a references request issued right
after it sees an AST cache holding nothing but the file it just opened and answers
with an empty list.

Force the scan rather than waiting for it. `completion` is one of the two requests
that call `updateNow` before consulting their provider, and
`DebouncingExecutor.executeNow` cancels the pending debounce and runs the update
synchronously on the request thread, so the response is not sent until that round
has finished. Two rounds suffice whatever the workspace size: the first drains the
pending file changes -- which is what re-defers the scan -- and the second finds
nothing pending, so it compiles the whole workspace before replying.

Polling the workspace symbol index instead would be unsound: `LanguageService.symbol`
neither awaits the update nor holds the monitor that `update` synchronises on. On a
generated 1050-file workspace, polling it made the server raise
`java.util.ConcurrentModificationException` from inside the scan, non-deterministically
(6, 3 and 0 times across three runs).

The existing cross-file reference test did not catch the empty results because the
`language_server` fixture is module-scoped: earlier tests in the class had already
opened main.nf and forced the server to compile it, so the assertion passed for a
reason that does not hold in a real session. Run alone, it failed. The added test
starts its own server and opens nothing but the defining file.

Verified on the 1050-file workspace, where the symbol has exactly 100 references:
without the fix 0 are found, with it all 100, in 2.5s.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 13:24:43 +02:00
weiconghe 1d44e9cfab feat: add Gleam language support via the Gleam compiler's bundled gleam lsp (#1765) 2026-08-08 19:44:27 +02:00
Merlin Hughes 8c1f3bcc98 Scala: give Metals the build roots rather than the repository root (#1767)
Metals serves one build per workspace folder, and Serena sends only the
repository root. Where the builds live below the root, Metals falls back to
its own search (BuildTools.searchForBuildTool), which looks one level down
and takes the *first* match — so in a monorepo every build but that one is
served with no build target, and cross-file references silently come back
empty.

Detect the build roots instead and send them all, one Metals service each.
`ls_specific_settings.scala.project_roots` names them explicitly where the
detection guesses wrong, `project_root_scan_depth` bounds the search.

The configured `ls_workspace_folders` are not usable for this: they are about
what SolidLSP indexes and are shared by every language server of a project, so
in a polyglot monorepo no single value suits both Metals and, say, tsserver.

Where the repository root is itself a build root, nothing changes.
2026-08-08 19:33:42 +02:00
Evangelos Karatzas 76b94f3274 Add Nextflow language server support (#1815)
The Nextflow language server schedules a debounced (1s) AST update on every
didOpen/didChange, and LanguageService.references is the only request that does
not await it -- documentSymbol, codeLens, documentLink and semanticTokensFull
all do. A references request issued inside that window races the recompile of
the file it asks about and can return an empty list, which is what the macOS CI
runner hit. Send a documentSymbol request for the same file first, which blocks
server-side until the pending update has been applied.

Also compare reference paths using the platform separator in the tests, since
relativePath is OS-native and the hardcoded forward slashes failed on Windows.
2026-08-08 18:58:46 +02:00
Michael Panchenko 27d7d0e0ec Merge pull request #1778 from shiersa/feat/deno-language-server
feat: add Deno language server support
2026-08-08 18:50:38 +02:00
Merlin Hughes 600d3b2fad Scala: answer Metals' build-import prompt (#1769)
* scala: answer Metals' build-import prompt

Metals asks, via window/showMessageRequest, whether to import a workspace it
has not seen before. Serena registered no handler, so the request came back
`method 'window/showMessageRequest' not handled on client` and Metals logged
"Unexpected error initializing server" and gave up. No build server, no build
target, and every cross-file query answered by the fallback presentation
compiler — which cannot see past the file it is given.

A client cannot decline the question instead: Metals' `disableShowMessageRequest`
is server-side configuration, and its no-op fallback answers "Not now", which
imports nothing either. Answering is the only route to a build.

So answer the three prompts that lead to a build server, and dismiss anything
else with `null` — a prompt we do not recognise is one whose consequences we
cannot judge, and two of Metals' others offer to kill a process and to open a
window. "Don't show again" is never chosen; Metals persists that in the
project's own state.

Since answering yes lets Metals run the project's build tool,
`ls_specific_settings.scala.auto_import_build: false` declines instead.

* scala: name the build-tool choice as a gap, and test the setting

`Messages.ChooseBuildTool` ("Multiple build definitions found. Which would
you like to use?") offers the build tools' own executable names, and precedes
the import prompt wherever a workspace holds more than one kind of build. It
is dismissed like anything else unrecognised, so such a workspace is still
not imported — a deliberate choice, since picking one is a guess of a
different order, but one the comment and the setup guide should admit to
rather than claim every prompt on the path is answered.

Also: cover the route from `ls_specific_settings` to `auto_import_build`,
which nothing exercised, and correct the `ImportBuildChanges` message in the
fixtures, which had the notification variant's trailing full stop rather than
the request's own text.
2026-08-08 16:28:04 +02:00
Tyce HerrmanandDominik Jain 217517ecdf feat(kotlin): update language server to 262.9593.0 (#1811)
* feat(kotlin): update language server to 262.9593.0

Note: download URL structure differs depending on version

---------

Co-authored-by: Dominik Jain <dominik.jain@oraios-ai.de>
2026-08-08 16:25:13 +02:00
Tyce Herrman 8364fc5548 fix(java): remove unused IntelliCode integration 2026-08-08 16:19:31 +02:00
shiersa 7a870878b8 feat: add Deno language server support
Add a Deno language server backed by the Deno CLI's built-in `deno lsp`,
serving TypeScript/JavaScript in Deno projects. Unlike the plain
typescript-language-server it understands Deno module resolution
(npm:/jsr:/https: imports) and the `Deno.*` global namespace.

It is experimental and must be selected explicitly via
`language_servers: [deno]`; it overlaps the TypeScript server on file
extensions, so it is not auto-detected. Requires the `deno` CLI on PATH.

Tests run in CI: the `deno` marker joins the other-langs batch, which now
installs Deno via denoland/setup-deno. Off-CI and wherever the CLI is
absent they skip through the central conftest guard, following the existing
pattern for toolchain-gated language servers. Hover is covered explicitly,
including hover on a `Deno.*` global, which is the capability this server
adds over the TypeScript one.
2026-08-06 23:21:42 +08:00
Tyce Herrman e03094f5bc fix(nix): use published diagnostics for nixd 2026-08-05 11:40:52 +02:00