use lsp_types::*;
use serde_json::json;
use super::*;
pub trait AddCommands {
fn add_commands(&mut self, cmds: &[String]);
}
pub struct RegularInit {
pub client: TypedLspClient<ServerState>,
pub font_opts: CompileFontArgs,
pub exec_cmds: Vec<String>,
}
impl AddCommands for RegularInit {
fn add_commands(&mut self, cmds: &[String]) {
self.exec_cmds.extend(cmds.iter().cloned());
}
}
impl Initializer for RegularInit {
type I = InitializeParams;
type S = ServerState;
fn initialize(self, params: InitializeParams) -> (ServerState, AnySchedulableResponse) {
let (config, err) = Config::extract_lsp_params(params, self.font_opts);
let super_init = SuperInit {
client: self.client,
exec_cmds: self.exec_cmds,
config,
err,
};
super_init.initialize(())
}
}
pub struct SuperInit {
pub client: TypedLspClient<ServerState>,
pub exec_cmds: Vec<String>,
pub config: Config,
pub err: Option<ResponseError>,
}
impl AddCommands for SuperInit {
fn add_commands(&mut self, cmds: &[String]) {
self.exec_cmds.extend(cmds.iter().cloned());
}
}
impl Initializer for SuperInit {
type I = ();
type S = ServerState;
fn initialize(self, _params: ()) -> (ServerState, AnySchedulableResponse) {
let SuperInit {
client,
exec_cmds,
config,
err,
} = self;
let const_config = config.const_config.clone();
let state = ServerState::main(client, config, err.is_none());
if let Some(err) = err {
return (state, Err(err));
}
let semantic_tokens_provider = (!const_config.tokens_dynamic_registration).then(|| {
SemanticTokensServerCapabilities::SemanticTokensOptions(get_semantic_tokens_options())
});
let document_formatting_provider =
(!const_config.doc_fmt_dynamic_registration).then_some(OneOf::Left(true));
let document_range_formatting_provider =
(!const_config.doc_fmt_dynamic_registration).then_some(OneOf::Left(true));
let file_operations = const_config.notify_will_rename_files.then(|| {
WorkspaceFileOperationsServerCapabilities {
will_rename: Some(FileOperationRegistrationOptions {
filters: vec![FileOperationFilter {
scheme: Some("file".to_string()),
pattern: FileOperationPattern {
glob: "**/*.typ".to_string(),
matches: Some(FileOperationPatternKind::File),
options: None,
},
}],
}),
..WorkspaceFileOperationsServerCapabilities::default()
}
});
let res = InitializeResult {
capabilities: ServerCapabilities {
position_encoding: Some(const_config.position_encoding.into()),
hover_provider: Some(HoverProviderCapability::Simple(true)),
signature_help_provider: Some(SignatureHelpOptions {
trigger_characters: Some(vec![
String::from("("),
String::from(","),
String::from(":"),
]),
retrigger_characters: None,
work_done_progress_options: WorkDoneProgressOptions {
work_done_progress: None,
},
}),
definition_provider: Some(OneOf::Left(true)),
references_provider: Some(OneOf::Left(true)),
completion_provider: Some(CompletionOptions {
trigger_characters: Some(vec![
String::from("#"),
String::from("("),
String::from("<"),
String::from(","),
String::from("."),
String::from(":"),
String::from("/"),
String::from("\""),
String::from("@"),
]),
..CompletionOptions::default()
}),
text_document_sync: Some(TextDocumentSyncCapability::Options(
TextDocumentSyncOptions {
open_close: Some(true),
change: Some(TextDocumentSyncKind::INCREMENTAL),
save: Some(TextDocumentSyncSaveOptions::Supported(true)),
..TextDocumentSyncOptions::default()
},
)),
semantic_tokens_provider,
execute_command_provider: Some(ExecuteCommandOptions {
commands: exec_cmds,
work_done_progress_options: WorkDoneProgressOptions {
work_done_progress: None,
},
}),
color_provider: Some(ColorProviderCapability::Simple(true)),
document_highlight_provider: Some(OneOf::Left(true)),
document_symbol_provider: Some(OneOf::Left(true)),
workspace_symbol_provider: Some(OneOf::Left(true)),
selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
rename_provider: Some(OneOf::Right(RenameOptions {
prepare_provider: Some(true),
work_done_progress_options: WorkDoneProgressOptions {
work_done_progress: None,
},
})),
document_link_provider: Some(DocumentLinkOptions {
resolve_provider: None,
work_done_progress_options: WorkDoneProgressOptions {
work_done_progress: None,
},
}),
folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
workspace: Some(WorkspaceServerCapabilities {
workspace_folders: Some(WorkspaceFoldersServerCapabilities {
supported: Some(true),
change_notifications: Some(OneOf::Left(true)),
}),
file_operations,
}),
document_formatting_provider,
document_range_formatting_provider,
inlay_hint_provider: Some(OneOf::Left(true)),
code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
code_lens_provider: Some(CodeLensOptions {
resolve_provider: Some(false),
}),
experimental: Some(json!({
"onEnter": true,
})),
..ServerCapabilities::default()
},
server_info: Some(ServerInfo {
name: "tinymist".to_string(),
version: Some(env!("CARGO_PKG_VERSION").to_string()),
}),
..InitializeResult::default()
};
let res = serde_json::to_value(res).map_err(|e| invalid_params(e.to_string()));
(state, just_result(res))
}
}