aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-12-31 11:21:23 +0000
committerGitHub <[email protected]>2020-12-31 11:21:23 +0000
commit53e2cdf18e155ad61262fed5dcd3d73ef343c042 (patch)
tree8414439a6141133dd2eb68ffd94f0ede306870f3
parent558206f70e418730967fd690f5f219993de071bc (diff)
parent5ce420ac8487d991ead53f51ae2d45ef33d4f94e (diff)
Merge #7055
7055: Install rustfmt if needed during formatting request r=matklad a=kinnison In order to fix #6052 and to fix #4249 this PR installs `rustfmt` using `rustup` if `rustfmt --help` fails. In theory we ought to memoise the attempts (both the `--help` and the installation) so that we don't keep retrying something which will fail (e.g. if nightly is missing rustfmt), but this is a first-pass for opinions. In order to make it possible to notify the user of what happened, I added a facility for `GlobalStateSnapshot` to send *messages* to the client indicating what happened. There may be a cleaner way to do this as well but I wasn't sure exactly what might be best given this is my first time in this codebase. It may be worth, longer term, working with `rustup` to provide a way to detect a missing component binary since `rustup` returns `1` if `rustfmt` is not installed, which is not ideal. Co-authored-by: Daniel Silverstone <[email protected]>
-rw-r--r--crates/rust-analyzer/src/handlers.rs11
1 files changed, 7 insertions, 4 deletions
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 23f323f55..78411f6c0 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -861,16 +861,18 @@ pub(crate) fn handle_formatting(
861 } 861 }
862 }; 862 };
863 863
864 let mut rustfmt = rustfmt.stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?; 864 let mut rustfmt =
865 rustfmt.stdin(Stdio::piped()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn()?;
865 866
866 rustfmt.stdin.as_mut().unwrap().write_all(file.as_bytes())?; 867 rustfmt.stdin.as_mut().unwrap().write_all(file.as_bytes())?;
867 868
868 let output = rustfmt.wait_with_output()?; 869 let output = rustfmt.wait_with_output()?;
869 let captured_stdout = String::from_utf8(output.stdout)?; 870 let captured_stdout = String::from_utf8(output.stdout)?;
871 let captured_stderr = String::from_utf8(output.stderr).unwrap_or_default();
870 872
871 if !output.status.success() { 873 if !output.status.success() {
872 match output.status.code() { 874 match output.status.code() {
873 Some(1) => { 875 Some(1) if !captured_stderr.contains("not installed") => {
874 // While `rustfmt` doesn't have a specific exit code for parse errors this is the 876 // While `rustfmt` doesn't have a specific exit code for parse errors this is the
875 // likely cause exiting with 1. Most Language Servers swallow parse errors on 877 // likely cause exiting with 1. Most Language Servers swallow parse errors on
876 // formatting because otherwise an error is surfaced to the user on top of the 878 // formatting because otherwise an error is surfaced to the user on top of the
@@ -886,8 +888,9 @@ pub(crate) fn handle_formatting(
886 format!( 888 format!(
887 r#"rustfmt exited with: 889 r#"rustfmt exited with:
888 Status: {} 890 Status: {}
889 stdout: {}"#, 891 stdout: {}
890 output.status, captured_stdout, 892 stderr: {}"#,
893 output.status, captured_stdout, captured_stderr,
891 ), 894 ),
892 ) 895 )
893 .into()); 896 .into());