Skip to content

Replace atom-editor-support with language-support XAR#68

Open
joewiz wants to merge 6 commits intowolfgangmm:masterfrom
joewiz:feature/language-support
Open

Replace atom-editor-support with language-support XAR#68
joewiz wants to merge 6 commits intowolfgangmm:masterfrom
joewiz:feature/language-support

Conversation

@joewiz
Copy link
Copy Markdown
Contributor

@joewiz joewiz commented Mar 14, 2026

Summary

  • Replace atom-editor-support XAR with a new language-support XAR that wraps eXist-db's lsp:* Java functions
  • Switch from GET-based endpoints with client-side import resolution to POST JSON endpoints with server-side import resolution
  • Support multi-error diagnostics (was: single error from util:compile-query)
  • Remove ~120 lines of client-side import parsing and resolution code
  • Cursor-based query execution via lsp:eval/lsp:fetch/lsp:close — replaces legacy POST /apps/atom-editor/execute
  • Output format settings — configurable serialization method and indent, with status bar, quick pick, and Lucene highlight-matches auto-detection

Closes #15request: and other eXist-db built-in namespace prefixes no longer trigger false XPST0081 errors, since lsp:diagnostics resolves them correctly (unlike the old util:compile-query path).

What changed

New companion XAR: existdb-language-support

  • Source: https://github.com/joewiz/existdb-language-support
  • Roaster-based REST API with 5 POST endpoints: /api/diagnostics, /api/symbols, /api/completions, /api/hover, /api/definition
  • Each endpoint accepts {query, base} (plus line, column for positional queries) and delegates to lsp:* functions
  • Bundled as resources/language-support-1.0.0.xar (replaces atom-editor-1.1.0.xar)

Cursor-based query execution

Replaces the legacy POST /apps/atom-editor/execute with a three-step cursor-based approach:

  1. lsp:eval($query, $base?) — executes the query, returns { cursor, items, elapsed }
  2. lsp:fetch($cursor, $start, $count) — fetches a page of results on demand
  3. lsp:close($cursor) — releases server-side resources

Server (server/src/analyzed-document.ts):

  • evalQuery() calls /api/eval, then auto-fetches the first page via /api/fetch
  • fetchResults() and closeCursor() support on-demand paging and cleanup
  • Legacy executeQuery() preserved as fallback when lsp:eval is unavailable

Server (server/src/server.ts):

  • Startup probe detects whether lsp:eval is available (sends query: '1', checks for cursor in response)
  • execute command routes to cursor-based or legacy path based on capability
  • New fetch and closeCursor commands

Client (client/src/extension.ts):

  • Execute command handles both cursor-based (array items) and legacy (string) results
  • New existdb.loadMoreResults command fetches the next page from an open cursor
  • Previous cursors are automatically closed before new queries

Client (client/src/query-results-provider.ts):

  • CursorState interface tracks active cursor, total hits, fetched count, output mode
  • appendResults() appends pages; clearCursor() resets state

Output format settings

Settings (package.json):

  • existdb.query.serializationMethod — default adaptive, enum: adaptive, xml, json, text
  • existdb.query.indent — default true, controls indentation of results

Client (client/src/extension.ts):

  • New existdb.setOutputFormat command — quick pick: Adaptive, XML, JSON, Text (with checkmark on current)
  • Clickable status bar item showing current output format (e.g., Adaptive)
  • getSerializationOptions() builds options object from settings, auto-enables highlight-matches: both when query contains ft:query or ft:search
  • Options threaded through execute and fetch commands to server

Server:

  • evalQuery() and fetchResults() accept optional serializationOptions parameter
  • Options forwarded as body.options in the /api/fetch REST call

server/src/linting.ts

  • serverLint(): POST to /apps/language-support/api/diagnostics (was PUT to compile.xql)
  • Handles structured JSON array of diagnostics with mapSeverity() (was regex-parsing a single error message)
  • Converts 1-indexed server responses to 0-indexed LSP protocol values

server/src/analyzed-document.ts

  • getCompletions(): POST full query text to /api/completions (was GET with resolved imports as query params)
  • getHoverRemote(): POST query + position to /api/hover (was GET with function signature)
  • gotoDefinitionRemote(): POST query + position to /api/definition (was GET with signature + client-side file reading)
  • Removed: resolveImports(), parseImports(), getParameters(), getOptions(), imports map, Import interface
  • Kept: local symbol lookup as first-try for hover/definition (no server roundtrip)

server/src/server.ts

  • Pass document text to getCompletions() and textDocument to getHover()
  • Semantic tokens provider: highlights function/variable declarations using server-side lsp:symbols, local fallback
  • Document formatting provider: XQuery formatting via Prettier + prettier-plugin-xquery
  • Enhanced document symbols: server-side lsp:symbols for richer outline (return types, parameter types), local fallback

server/src/utils.ts

  • checkServer(): detect http://exist-db.org/apps/language-support (was atom-editor)

Tests

27 tests total (26 new). Run with:

npm test

test/cursor-execution.spec.ts (11 tests):

  • evalQuery: eval→fetch two-step, output mode detection, custom page size, error propagation
  • fetchResults: correct params, empty results
  • closeCursor: success/failure returns
  • executeQuery legacy: atom-editor endpoint, form-encoded body

test/capability-check.spec.ts (7 tests):

  • Capability detection: cursor probe succeeds, 404, unreachable, bad response, close-failure resilience
  • Command routing: evalQuery when capable, legacy when not

test/serialization-options.spec.ts (10 tests):

  • Options pass-through in evalQuery and fetchResults
  • Options omitted when undefined
  • highlight-matches forwarding
  • Lucene ft:query/ft:search regex detection (positive and negative cases)

Known limitation: xqlint client-side pass

This PR retains the xqlint client-side pass, which serves two purposes:

  1. getAST() — builds an AST used for local symbol lookup (finding which function call the cursor is on, for hover/go-to-definition without a server roundtrip)
  2. getWarnings()removed in this PR. Server-side lsp:diagnostics handles error checking without the false positives xqlint produces (e.g., false positive problem reports "unused variable" #67).

A future improvement would be to swap xqlint entirely for eXide's REx-generated parser, which produces a correct AST from the W3C XQuery 3.1 grammar.

Requirements

Test plan

  • Install language-support XAR on eXist-db with lsp:* module
  • Verify all 5 endpoints with curl
  • Open workspace with .existdb.json in VS Code Extension Development Host
  • Diagnostics: red squiggles on invalid XQuery (multi-error, correct line)
  • Completions: local + built-in functions appear as you type
  • Hover: function signatures shown on hover
  • Go-to-definition: jumps to function declaration
  • Outline: document symbols with return types (server-enhanced)
  • Semantic highlighting: function/variable declarations highlighted
  • XQuery formatting: Shift+Alt+F formats XQuery code via Prettier
  • Cross-module go-to-definition: jumps to imported module functions
  • Status bar: database icon shows workspace name, no install prompt when XAR is current
  • No false XPST0081 error on request:get-parameter (VSCode objects to "request:" namespace prefix #15)
  • No false [W03] Unused variable warnings (false positive problem reports "unused variable" #67 — xqlint warnings removed)
  • Cursor-based execution: run query, verify cursor + first page returned
  • Load More Results: fetch subsequent pages from open cursor
  • Fallback: verify legacy execution when lsp:eval is unavailable
  • Output format status bar: shows current method, clickable to change
  • Set Output Format: quick pick changes existdb.query.serializationMethod
  • Serialization options: XML/JSON/Text modes produce correctly formatted output
  • Lucene highlight: ft:query in query auto-enables highlight-matches
  • npm test passes (27 tests)

🤖 Generated with Claude Code

joewiz and others added 4 commits March 13, 2026 23:09
Switch from atom-editor-support (GET-based, single error, client-side
import resolution) to language-support (POST JSON, multi-error diagnostics,
server-side import resolution via lsp:* functions).

Key changes:
- linting.ts: POST /api/diagnostics with structured JSON response
- analyzed-document.ts: POST /api/{completions,hover,definition} with
  full query text; removed resolveImports/parseImports/getParameters
- server.ts: pass document text to getCompletions and getHover
- utils.ts: detect language-support XAR instead of atom-editor

Requires eXist-db 7.0+ with lsp:* module (eXist-db/exist#6130).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- linting.ts: remove getWarnings() call, keep only getAST() for local
  symbol lookup. Eliminates false positives like wolfgangmm#67 (unused variable
  with arrow operator). Server-side lsp:diagnostics handles error checking.
- analyzed-document.ts: handle "uri" field from lsp:definition response
  for cross-module go-to-definition. Maps database paths to workspace
  file URIs using settings.path prefix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three new LSP capabilities for parity with eXide:

- Semantic tokens: highlights function and variable declarations using
  server-side lsp:symbols, with local fallback
- Document formatting: Prettier-based XQuery formatting via
  prettier-plugin-xquery (XQuery files only — VS Code handles other
  languages natively)
- Enhanced document symbols: uses server-side lsp:symbols for richer
  outline with return types and parameter types, local fallback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Calls /api/references to find all usages of the symbol at cursor.
Enables VS Code's "Find All References" (Shift+F12) and "Rename
Symbol" (F2) for XQuery functions and variables.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
joewiz and others added 2 commits March 22, 2026 15:31
Replace the legacy POST /apps/atom-editor/execute calls with cursor-based
execution through the language-support XAR API (lsp:eval/fetch/close).

Server: evalQuery() calls /api/eval to get a cursor handle then fetches the
first page via /api/fetch. fetchResults() and closeCursor() support paging
and cleanup. Legacy executeQuery() preserved as fallback when lsp:eval is
unavailable — detected at startup via a probe request.

Client: execute command now handles both cursor-based (array items) and
legacy (string) results. New "Load More Results" command fetches subsequent
pages. Previous cursors are closed before new queries.

Tests: 16 new Mocha tests covering eval/fetch/close lifecycle, capability
detection (success, 404, unreachable, bad response, close-failure), command
routing, and legacy fallback. Run with `npm test`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New settings: existdb.query.serializationMethod (adaptive/xml/json/text)
and existdb.query.indent (boolean). These control how lsp:fetch serializes
query results.

New command: "eXist-db: Set Output Format" — quick pick to change the
serialization method, with a clickable status bar item showing the current
format.

Serialization options (method, indent) are threaded from the client through
the server to the lsp:fetch REST call. For Lucene queries containing
ft:query or ft:search, highlight-matches is automatically enabled.

10 new tests covering option pass-through and Lucene detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

VSCode objects to "request:" namespace prefix

1 participant