Syntax Reference
LanguageServer.LanguageServerInstanceLanguageServer.PhaseBarLanguageServer.RangeLanguageServer._convert_completion_editLanguageServer._create_deferred_progress_callbackLanguageServer.apply_text_editsLanguageServer.directory_watching_modeLanguageServer.get_offsetLanguageServer.get_position_from_offsetLanguageServer.handle_publish_sweep_msg!LanguageServer.index_atLanguageServer.is_diag_dependent_on_envLanguageServer.jw_position_to_lspLanguageServer.jw_rangeLanguageServer.jw_source_textLanguageServer.jw_textLanguageServer.jw_versionLanguageServer.publish_file_diagnostics_testitemsLanguageServer.reconcile_indirect_file_watchersLanguageServer.request_indexing_refreshLanguageServer.run_diagnostic_publish_sweepLanguageServer.run_publish_sweepLanguageServer.run_testitem_publish_sweepLanguageServer.runserverLanguageServer.schedule_publish_sweep!LanguageServer.should_watch_directoriesLanguageServer.testitem_identification_enabled
Main
LanguageServer.LanguageServerInstance — Type
LanguageServerInstance(pipe_in, pipe_out, env="", depot="", err_handler=nothing, symserver_store_path=nothing)Construct an instance of the language server.
Once the instance is run, it will read JSON-RPC from pipe_out and write JSON-RPC from pipe_in according to the language server specification. For normal usage, the language server can be instantiated with LanguageServerInstance(stdin, stdout, false, "/path/to/environment").
Arguments
pipe_in::IO: Pipe to read JSON-RPC from.pipe_out::IO: Pipe to write JSON-RPC to.env::String: Path to the environment for which the language server is running. An empty string uses julia's default environment.depot::String: Sets theJULIA_DEPOT_PATHwhere the language server looks for packages required inenv.err_handler::Union{Nothing,Function}: If notnothing, catch all errors and pass them to an error handler function with signatureerr_handler(err, bt). Mostly used for the VS Code crash reporting implementation.symserver_store_path::Union{Nothing,String}: ifnothingis passed, the symbol server cash is stored in a folder in the package. If an absolute path is passed, the symbol server will store the cache files in that path. The path must exist on disc before this is called.
LanguageServer.request_indexing_refresh — Method
run(server::LanguageServerInstance)Run the language server.
LanguageServer.PhaseBar — Type
create_progress_callback(server::LanguageServerInstance) -> FunctionReturn a closure (key::String, message::String, percentage::Int) -> Nothing that translates JuliaWorkspaces progress updates into LSP $/progress notifications.
Reports are aggregated by phase — the part of key before : (index, download, refresh), or the whole key for single-operation phases (package-caches, bootstrap). Each phase is one bar, so a workspace with dozens of environments shows a single "Indexing environments (k/N)..." bar instead of dozens. For index/refresh the percentage tracks the count of completed keys (k/N), so an in-progress environment never advances the bar past that count; the download bar keeps the mean, since a download key carries a real fraction. The bar ends once every key has reported >= 100.
The closure only enqueues the report and never blocks: a worker task owns the token lifecycles and does the client round-trips, so a report arriving while a token is being created queues up and is delivered in order.
LanguageServer._create_deferred_progress_callback — Method
_create_deferred_progress_callback(server_ref::Ref{LanguageServerInstance}) -> FunctionReturn a progress callback that defers to create_progress_callback once server_ref has been assigned (after the inner constructor completes). This allows the callback to be passed to JuliaWorkspace during construction while the LanguageServerInstance is still being built.
LanguageServer.runserver — Function
runserver(pipe_in=stdin, pipe_out=stdout[, env_path])Run a LanguageServerInstance reading from pipe_in and writing to pipe_out.
The same options can be passed to runserver as to LanguageServerInstance. If env_path is not specified, attempt to pick an environment by considering in order of priority:
ARGS[1]: the first command-line argument passed to the invocation ofjulia.- The Julia project containing
pwd(). - The default Julia environment withing
.julia/environments/v#.#.
Examples
The following invocation of Julia would set env_path to /home/example/repos/Example.jl:
julia --project=/path/to/LanguageServer.jl \
-e "using LanguageServer; runserver()" \
/home/example/repos/Example.jlIf there was a Project.toml or JuliaProject.toml in /home/example/repos/Example.jl/, the following invocation would set env_path to /home/example/repos/Example.jl/; otherwise it would be set to .julia/environments/v#.# where v#.# is the major/minor version of Julia being invoked.
julia --project=/path/to/LanguageServer.jl \
-e "using LanguageServer; runserver()"LanguageServer.jw_position_to_lsp — Method
jw_position_to_lsp(server, uri, pos)Convert a JuliaWorkspaces.Position (1-based line, 1-based UTF-8 byte column) to an LSP Position (0-based line, 0-based UTF-16 character).
When column == 1, the conversion is trivial (character = 0) and no SourceText lookup is needed.
LanguageServer.jw_range — Method
jw_range(server, uri, start, stop)Convert a pair of JuliaWorkspaces.Position values to an LSP Range.
LanguageServer.jw_source_text — Method
jw_source_text(server, uri)Get the SourceText for a URI from JuliaWorkspaces.
LanguageServer.jw_text — Method
jw_text(server, uri)Get the file content string for a URI.
LanguageServer.jw_version — Method
jw_version(server, uri)Get the LSP document version for a URI (from open file tracking).
LanguageServer.handle_publish_sweep_msg! — Method
handle_publish_sweep_msg!(server, generation)Dispatch-loop handler for :publish_sweep messages. Messages from superseded schedules are ignored. When other messages are already queued (e.g. interactive requests) and the max-latency budget has not run out, the sweep re-enqueues itself behind them instead of blocking the queue.
LanguageServer.publish_file_diagnostics_testitems — Method
publish_file_diagnostics_testitems(server, uris)Immediately publish diagnostics and testitems for the given files (used for the file a mutation directly targets, so in-editor feedback does not wait for the debounced sweep). Publishes only when the file's state differs from what the client last received, and records the published hashes so the following sweep does not resend it.
LanguageServer.reconcile_indirect_file_watchers — Method
reconcile_indirect_file_watchers(server::LanguageServerInstance)Compares JuliaWorkspaces' current set of indirect files against server._watched_indirect_files and sends client/registerCapability for newly-introduced indirect URIs and client/unregisterCapability for URIs that are no longer indirect (because they were promoted, removed from the include graph, or deleted on disc). Also performs an initial disc read for freshly-watched URIs and feeds the content back in via set_indirect_file_content!.
LanguageServer.run_diagnostic_publish_sweep — Method
run_diagnostic_publish_sweep(server)Bring the whole workspace's published diagnostics up to date. This is the one place the full workspace lint is pulled, so it also serves as the consistency point after mutations — hence the indirect-file watcher reconciliation.
LanguageServer.run_publish_sweep — Method
run_publish_sweep(server)Bring the whole workspace's published diagnostics and testitems up to date: compute current per-file hashes, diff them against server._published_hashes (what the client last received), publish only the differences, and record the new state.
Testitems go first: they are cheap and environment-independent, so there is no reason for them to sit behind the full workspace lint.
LanguageServer.run_testitem_publish_sweep — Method
run_testitem_publish_sweep(server)Bring the whole workspace's published testitems up to date. Split out of run_publish_sweep so it can run on its own during startup: testitem discovery is purely static (file text plus Project.toml identity — no environment resolution, no dynamic indexing), so it must not wait behind the full workspace lint that the diagnostics half pulls.
LanguageServer.schedule_publish_sweep! — Method
schedule_publish_sweep!(server)Mark the workspace dirty and (re)arm the debounce timer for the publish sweep. Every call supersedes previously scheduled sweeps (the generation counter makes their queued messages stale), so a burst of mutations results in a single sweep. Must be called from the dispatch task; the timer callback only ever touches the (task-safe) message queue.
LanguageServer.testitem_identification_enabled — Method
testitem_identification_enabled(server)Whether the client asked for test item identification at initialization. This is the single gate for all testitem work: when it is off, we neither compute nor publish test items (computing them re-parses every file, which is not free).
LanguageServer.Range — Method
Range(st::JuliaWorkspaces.SourceText, rng::UnitRange)Converts a 1-based half-open byte range (as produced by JuliaWorkspaces diagnostics and test items) to an LSP Range with UTF-16 character encoding. first(rng) is the 1-based inclusive start byte and last(rng) is the 1-based exclusive end.
Offsets are clamped to the document's byte length: a diagnostic or test-item range may be computed against a slightly newer/older revision of the content than the SourceText passed here (the analysis result and the document can race), and an out-of-bounds offset must degrade to the document end rather than crash the whole request via get_position_from_offset.
LanguageServer.apply_text_edits — Method
apply_text_edits(st::JuliaWorkspaces.SourceText, edits)Apply LSP text edits to a SourceText and return the new content as a String.
LanguageServer.get_offset — Method
get_offset(st, line, char)Returns the 0 based byte offset position corresponding to a line/character position. This takes 0 based line/char inputs. Corresponding functions are available for Position and Range arguments, the latter returning a UnitRange{Int}.
LanguageServer.get_position_from_offset — Method
get_position_from_offset(st, offset)Returns the 0-based line and character position within a document of a given byte offset. Handles UTF-16 encoding for LSP compliance.
LanguageServer.index_at — Function
index_at(st::JuliaWorkspaces.SourceText, p::Position, forgiving_mode=false)Converts a 0-based Position that is UTF-16 encoded to a 1-based UTF-8 encoded Julia string index.
LanguageServer.directory_watching_mode — Method
directory_watching_mode(server) -> "auto" | "on" | "off"The client's directory-watching preference from the initializationOptions key "julialangDirectoryWatching". Accepts "on"/"off" (booleans are mapped to them); anything else, including the key being absent, means "auto".
LanguageServer.should_watch_directories — Method
should_watch_directories(server) -> BoolWhether to additionally register a ** create/delete watcher so that atomic folder renames and deletes are observed. VS Code's file watcher reports those as a single event for the folder path with no per-child events, so without the extra watcher the server never notices them; most other clients' watcher backends synthesize per-file events, making the plain file-extension globs sufficient there — and some (e.g. Emacs-based clients) expand ** into one OS watcher per directory, so it must not be forced on them.
In the default "auto" mode this is enabled for clients of the Code-OSS family (detected via clientInfo.name). Any client can override the guess through initializationOptions: { "julialangDirectoryWatching": "on" | "off" }.
Requests
LanguageServer._convert_completion_edit — Method
Convert a JuliaWorkspaces.CompletionEdit (Position-based) to an LSP TextEdit.
LanguageServer.is_diag_dependent_on_env — Method
isdiagdependentonenv(diag::Diagnostic)::Bool
Is this diagnostic reliant on the current environment being accurately represented?