use emmylua_code_analysis::range_format_code;
use lsp_types::{
ClientCapabilities, DocumentRangeFormattingParams, OneOf, Position, Range, ServerCapabilities,
TextEdit,
};
use tokio_util::sync::CancellationToken;
use crate::context::ServerContextSnapshot;
pub async fn on_range_formatting_handler(
context: ServerContextSnapshot,
params: DocumentRangeFormattingParams,
_: CancellationToken,
) -> Option<Vec<TextEdit>> {
let uri = params.text_document.uri;
let request_range = params.range;
let analysis = context.analysis.read().await;
let config_manager = context.config_manager.read().await;
let client_id = config_manager.client_config.client_id;
let file_id = analysis.get_file_id(&uri)?;
let semantic_model = analysis.compilation.get_semantic_model(file_id)?;
let document = semantic_model.get_document();
let text = document.get_text();
let file_path = document.get_file_path();
let normalized_path = file_path.to_string_lossy().to_string().replace("\\", "/");
let formatted_result = range_format_code(
text,
&normalized_path,
request_range.start.line as i32,
request_range.start.character as i32,
request_range.end.line as i32,
request_range.end.character as i32,
);
let mut formatted_text = formatted_result.text;
if client_id.is_intellij() || client_id.is_other() {
formatted_text = formatted_text.replace("\r\n", "\n");
}
let text_edit = TextEdit {
range: Range {
start: Position {
line: formatted_result.start_line as u32,
character: formatted_result.start_col as u32,
},
end: Position {
line: formatted_result.end_line as u32 + 1,
character: 0,
},
},
new_text: formatted_text,
};
Some(vec![text_edit])
}
pub fn register_capabilities(
server_capabilities: &mut ServerCapabilities,
_: &ClientCapabilities,
) -> Option<()> {
server_capabilities.document_range_formatting_provider = Some(OneOf::Left(true));
Some(())
}