|
| 1 | +use std::io::Write; |
| 2 | + |
1 | 3 | use anyhow::Ok; |
2 | 4 | use starpls_ide::CompletionItemKind; |
3 | 5 | use starpls_ide::CompletionMode::InsertText; |
@@ -287,6 +289,62 @@ pub(crate) fn document_symbols( |
287 | 289 | })) |
288 | 290 | } |
289 | 291 |
|
| 292 | +pub(crate) fn formatting( |
| 293 | + snapshot: &ServerSnapshot, |
| 294 | + params: lsp_types::DocumentFormattingParams, |
| 295 | +) -> anyhow::Result<Option<Vec<lsp_types::TextEdit>>> { |
| 296 | + let path = path_buf_from_url(¶ms.text_document.uri)?; |
| 297 | + let file_id = try_opt!(snapshot.document_manager.read().lookup_by_path_buf(&path)); |
| 298 | + let line_index = try_opt!(snapshot.analysis_snapshot.line_index(file_id)?); |
| 299 | + let default_buildifier_config; |
| 300 | + let buildifier = match &snapshot.config.buildifier { |
| 301 | + Some(config) => config, |
| 302 | + None => { |
| 303 | + default_buildifier_config = Default::default(); |
| 304 | + &default_buildifier_config |
| 305 | + } |
| 306 | + }; |
| 307 | + |
| 308 | + // Read the file's contents. |
| 309 | + let contents = try_opt!(snapshot.analysis_snapshot.file_contents(file_id)?); |
| 310 | + |
| 311 | + // Spawn buildifier. |
| 312 | + let mut command = |
| 313 | + std::process::Command::new(buildifier.path.as_deref().unwrap_or("buildifier")); |
| 314 | + command.args(&buildifier.args); |
| 315 | + command.arg("-"); |
| 316 | + let mut child = command |
| 317 | + .stdin(std::process::Stdio::piped()) |
| 318 | + .stdout(std::process::Stdio::piped()) |
| 319 | + .spawn()?; |
| 320 | + |
| 321 | + // Write the file's contents to stdin. |
| 322 | + let mut stdin = child.stdin.take().unwrap(); |
| 323 | + stdin.write_all(contents.as_bytes())?; |
| 324 | + drop(stdin); |
| 325 | + |
| 326 | + // Read the formatted output from stdout. |
| 327 | + let output = child.wait_with_output()?; |
| 328 | + if !output.status.success() { |
| 329 | + return Ok(None); |
| 330 | + } |
| 331 | + let new_text = String::from_utf8(output.stdout)?; |
| 332 | + |
| 333 | + // Replace the entire document with the formatted text. |
| 334 | + let range = lsp_types::Range { |
| 335 | + start: lsp_types::Position { |
| 336 | + line: 0, |
| 337 | + character: 0, |
| 338 | + }, |
| 339 | + end: lsp_types::Position { |
| 340 | + line: line_index.len().into(), |
| 341 | + character: 0, |
| 342 | + }, |
| 343 | + }; |
| 344 | + |
| 345 | + Ok(Some(vec![lsp_types::TextEdit { range, new_text }])) |
| 346 | +} |
| 347 | + |
290 | 348 | fn to_markup_doc(doc: String) -> lsp_types::Documentation { |
291 | 349 | lsp_types::Documentation::MarkupContent(lsp_types::MarkupContent { |
292 | 350 | kind: lsp_types::MarkupKind::Markdown, |
|
0 commit comments