use crate::error::Language;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LanguageServerConfig {
pub name: String,
pub command: String,
pub args: Vec<String>,
#[serde(default)]
pub env: HashMap<String, String>,
pub file_extensions: Vec<String>,
pub language_id: String,
#[serde(default)]
pub initialization_options: Option<serde_json::Value>,
#[serde(default = "default_timeout")]
pub timeout_secs: u64,
}
fn default_timeout() -> u64 {
30
}
#[derive(Debug, Clone)]
pub struct LanguageServerRegistry {
configs: HashMap<Language, LanguageServerConfig>,
}
impl Default for LanguageServerRegistry {
fn default() -> Self {
Self::new()
}
}
impl LanguageServerRegistry {
pub fn new() -> Self {
let mut configs = HashMap::new();
configs.insert(
Language::Rust,
LanguageServerConfig {
name: "rust-analyzer".to_string(),
command: "rust-analyzer".to_string(),
args: vec![],
env: HashMap::new(),
file_extensions: vec!["rs".to_string()],
language_id: "rust".to_string(),
initialization_options: None,
timeout_secs: 30,
},
);
configs.insert(
Language::TypeScript,
LanguageServerConfig {
name: "typescript-language-server".to_string(),
command: "typescript-language-server".to_string(),
args: vec!["--stdio".to_string()],
env: HashMap::new(),
file_extensions: vec![
"ts".to_string(),
"tsx".to_string(),
"js".to_string(),
"jsx".to_string(),
],
language_id: "typescript".to_string(),
initialization_options: None,
timeout_secs: 30,
},
);
configs.insert(
Language::JavaScript,
LanguageServerConfig {
name: "typescript-language-server".to_string(),
command: "typescript-language-server".to_string(),
args: vec!["--stdio".to_string()],
env: HashMap::new(),
file_extensions: vec!["js".to_string(), "jsx".to_string(), "mjs".to_string()],
language_id: "javascript".to_string(),
initialization_options: None,
timeout_secs: 30,
},
);
configs.insert(
Language::Python,
LanguageServerConfig {
name: "pyright".to_string(),
command: "pyright-langserver".to_string(),
args: vec!["--stdio".to_string()],
env: HashMap::new(),
file_extensions: vec!["py".to_string(), "pyi".to_string()],
language_id: "python".to_string(),
initialization_options: None,
timeout_secs: 30,
},
);
configs.insert(
Language::Go,
LanguageServerConfig {
name: "gopls".to_string(),
command: "gopls".to_string(),
args: vec!["serve".to_string()],
env: HashMap::new(),
file_extensions: vec!["go".to_string()],
language_id: "go".to_string(),
initialization_options: None,
timeout_secs: 30,
},
);
configs.insert(
Language::Cpp,
LanguageServerConfig {
name: "clangd".to_string(),
command: "clangd".to_string(),
args: vec![],
env: HashMap::new(),
file_extensions: vec![
"cpp".to_string(),
"cc".to_string(),
"cxx".to_string(),
"hpp".to_string(),
"h".to_string(),
],
language_id: "cpp".to_string(),
initialization_options: None,
timeout_secs: 30,
},
);
configs.insert(
Language::C,
LanguageServerConfig {
name: "clangd".to_string(),
command: "clangd".to_string(),
args: vec![],
env: HashMap::new(),
file_extensions: vec!["c".to_string(), "h".to_string()],
language_id: "c".to_string(),
initialization_options: None,
timeout_secs: 30,
},
);
Self { configs }
}
pub fn get(&self, language: Language) -> Option<&LanguageServerConfig> {
self.configs.get(&language)
}
pub fn register(&mut self, language: Language, config: LanguageServerConfig) {
self.configs.insert(language, config);
}
pub fn languages(&self) -> impl Iterator<Item = &Language> {
self.configs.keys()
}
}