Add support for formatting entire document with rustfmt

Attempting to format a document when rustfmt isn't installed will result
in an error being returned to the frontend. An alternative
implementation would be returning zero replacements.
This commit is contained in:
Aleksander Vognild Burkow 2018-12-29 20:09:42 +01:00
parent 2aac6b0e34
commit 8b24f158f7
6 changed files with 95 additions and 3 deletions

View file

@ -33,7 +33,7 @@ pub fn server_capabilities() -> ServerCapabilities {
workspace_symbol_provider: Some(true),
code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
code_lens_provider: None,
document_formatting_provider: None,
document_formatting_provider: Some(true),
document_range_formatting_provider: None,
document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
first_trigger_character: "=".to_string(),

View file

@ -295,6 +295,7 @@ fn on_request(
.on::<req::PrepareRenameRequest>(handlers::handle_prepare_rename)?
.on::<req::Rename>(handlers::handle_rename)?
.on::<req::References>(handlers::handle_references)?
.on::<req::Formatting>(handlers::handle_formatting)?
.finish();
match req {
Ok(id) => {

View file

@ -6,13 +6,16 @@ use languageserver_types::{
DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind,
FoldingRangeParams, Location, MarkupContent, MarkupKind, MarkedString, Position,
PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit,
Range,
WorkspaceEdit, ParameterInformation, ParameterLabel, SignatureInformation, Hover, HoverContents,
DocumentFormattingParams,
};
use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FileRange, FilePosition, Severity};
use ra_syntax::{TextUnit, text_utils::intersect};
use ra_text_edit::text_utils::contains_offset_nonstrict;
use rustc_hash::FxHashMap;
use serde_json::to_value;
use std::io::Write;
use crate::{
conv::{to_location, Conv, ConvWith, MapConvWith, TryConvWith},
@ -601,6 +604,36 @@ pub fn handle_references(
))
}
pub fn handle_formatting(
world: ServerWorld,
params: DocumentFormattingParams,
) -> Result<Option<Vec<TextEdit>>> {
let file_id = params.text_document.try_conv_with(&world)?;
let file = world.analysis().file_text(file_id);
let file_line_index = world.analysis().file_line_index(file_id);
let end_position = TextUnit::of_str(&file).conv_with(&file_line_index);
use std::process;
let mut rustfmt = process::Command::new("rustfmt")
.stdin(process::Stdio::piped())
.stdout(process::Stdio::piped())
.spawn()?;
rustfmt.stdin.as_mut().unwrap().write_all(file.as_bytes())?;
let output = rustfmt.wait_with_output()?;
let captured_stdout = String::from_utf8(output.stdout)?;
if !output.status.success() {
return Err(failure::err_msg(captured_stdout));
}
Ok(Some(vec![TextEdit {
range: Range::new(Position::new(0, 0), end_position),
new_text: captured_stdout,
}]))
}
pub fn handle_code_action(
world: ServerWorld,
params: req::CodeActionParams,