use std::process::ExitCode;
use std::sync::Arc;
use clap::Parser;
use mago_analyzer::plugin::create_registry_with_plugins;
use crate::config::Configuration;
use crate::error::Error;
use crate::language_server::ServerConfig;
#[derive(Parser, Debug)]
#[command(
name = "language-server",
about = "Start the Mago language server (LSP over stdio).",
long_about = indoc::indoc! {r"
Start the Mago language server, speaking LSP over stdio. Editors
invoke this as a child process and route their requests through it.
Each subsystem can be turned off when an editor doesn't need it,
for a smaller footprint or a faster bootstrap. Pass
--no-analyzer --no-formatter for a diagnostics-only profile.
**NOTE**: The LSP is a work in progress. The set of advertised capabilities,
the wire behaviour, the flags below, and even the existence of
this subcommand can change or disappear without notice. There are
no compatibility guarantees until mago 2.0. if you need a stable
editor integration, wait for that release.
"}
)]
pub struct LanguageServerCommand {
#[arg(long, default_value_t = false)]
pub no_analyzer: bool,
#[arg(long, default_value_t = false)]
pub no_linter: bool,
#[arg(long, default_value_t = false)]
pub no_formatter: bool,
}
impl LanguageServerCommand {
pub fn execute(self, configuration: Configuration) -> Result<ExitCode, Error> {
let plugin_registry = Arc::new(create_registry_with_plugins(
&configuration.analyzer.plugins,
configuration.analyzer.disable_default_plugins,
));
let config = ServerConfig {
analyzer: !self.no_analyzer,
linter: !self.no_linter,
formatter: !self.no_formatter,
configuration,
plugin_registry,
};
let runtime =
tokio::runtime::Builder::new_multi_thread().enable_all().build().map_err(Error::BuildingRuntime)?;
runtime.block_on(crate::language_server::run(config));
Ok(ExitCode::SUCCESS)
}
}