Configuring a server
Pre-requisites
The server is generic over a salsa::Database
, so you need to implement a database before starting the server.
You can use the default BaseDb
database provided by auto_lsp
or create your own.
The default
module in server contains a file storage and file event handlers and workspace loading logic that are compatible with the BaseDatabase
trait.
If you create your own database, you will have to create your own file storage and file event handlers.
Configuring
To configure a server, you need to use the create
method from the Session
struct wich takes 4 arguments.
parsers
: A list of parsers (previously defined with theconfigure_parsers!
macro)capabilities
: Server capabilities, see ServerCapabilities.server_info
: Optional information about the server, such as its name and version, see ServerInfo.connection
: The connection to the client, see Connection.db
: The database to use, it must implementsalsa::Database
.
create
will return a tuple containing the Session
and the InitializeParams sent by the client.
The server communicates with an LSP client using one of lsp_server's tranport methods: stdio
, tcp
or memory
.
use std::error::Error;
use auto_lsp::server::{InitOptions, Session, ServerCapabilities};
use ast_python::db::PYTHON_PARSERS;
fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
// Enable logging and tracing, this is optional
stderrlog::new()
.modules([module_path!(), "auto_lsp"])
.verbosity(4)
.init()
.unwrap();
fastrace::set_reporter(ConsoleReporter, Config::default());
// Server options
let options = InitOptions {
parsers: &PYTHON_PARSERS,
capabilities: ServerCapabilities {
..Default::default()
},
server_info: None,
};
// Create the connection
let (connection, io_threads) = Connection::stdio();
// Create a database, either BaseDb or your own
let db = BaseDb::default();
// Create the session
let (mut session, params) = Session::create(
options,
connection,
db,
)?;
// This is where you register your requests and notifications
// See the handlers section for more information
let mut request_registry = RequestRegistry::<BaseDb>::default();
let mut notification_registry = NotificationRegistry::<BaseDb>::default();
// This will add all files available in the workspace.
// The init_workspace is only available for databases that implement BaseDatabase or BaseDb
let init_results = session.init_workspace(params)?;
if !init_results.is_empty() {
init_results.into_iter().for_each(|result| {
if let Err(err) = result {
eprintln!("{}", err);
}
});
};
// Run the server and wait for the two threads to end (typically by trigger LSP Exit event).
session.main_loop(
&mut request_registry,
&mut notification_registry,
)?;
session.io_threads.join()?;
// Shut down gracefully.
eprintln!("Shutting down server");
Ok(())
}
Default Capabilities
auto_lsp
provides helper methods to configure some default capabilities.
Semantic Tokens
The semantic_tokens_provider
method will configure the semantic_tokens_provider
field of the ServerCapabilities
struct.
Parameters:
range
: Whether the client supports to send requests for semantic tokens for a specific range.token_types
: The list of token types that the server supports.token_modifiers
: The list of token modifiers that the server supports.
use auto_lsp::server::semantic_tokens_provider;
let capabilities = ServerCapabilities {
semantic_tokens_provider: semantic_tokens_provider(false, Some(SUPPORTED_TYPES), Some(SUPPORTED_MODIFIERS)),
..Default::default()
};
Except for semantic tokens, these default capabilities are only available if you use the BaseDb
database.
Text Document Sync
Since the Document
supports incremental updates, the text_document_sync
field of the ServerCapabilities
struct is configured to INCREMENTAL
by default.
You can use the TEXT_DOCUMENT_SYNC
constant to configure it.
use auto_lsp::server::TEXT_DOCUMENT_SYNC;
let capabilities = ServerCapabilities {
text_document_sync: TEXT_DOCUMENT_SYNC.clone(),
..Default::default()
};
This is meant to be used for the default handler open_text_document
to work.
Workspace Provider
The WORKSPACE_PROVIDER
constant will configure the workspace
field of the ServerCapabilities
struct.
use auto_lsp::server::WORKSPACE_PROVIDER;
let capabilities = ServerCapabilities {
workspace: WORKSPACE_PROVIDER.clone(),
..Default::default()
};
This is meant to be used for the default handler changed_watched_files
to work.
Workspace initialization
When using BaseDb
as the database, the init_workspace
method will load all files in the workspace and associate them with a parser.
It will also send diagnostics for all files.
If you want to customize this behavior, you can implement your own init_workspace
method and call it instead of the default one.
use auto_lsp::server::Session;
let (mut session, params) = Session::create(
options,
connection,
db,
)?;
// This will add all files available in the workspace.
let init_results = my_init_workspace(&mut session, params)?;
if !init_results.is_empty() {
init_results.into_iter().for_each(|result| {
if let Err(err) = result {
eprintln!("{}", err);
}
});
};