Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit 1ad894b

Browse files
committed
Redo errors in format.rs
1 parent 6a1b5a9 commit 1ad894b

File tree

3 files changed

+53
-31
lines changed

3 files changed

+53
-31
lines changed

rls/src/actions/format.rs

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::fs::File;
66
use std::io::Write;
77
use std::path::{Path, PathBuf};
88
use std::process::{Command, Stdio};
9+
use std::string::FromUtf8Error;
910

1011
use log::debug;
1112
use rand::{distributions, thread_rng, Rng};
@@ -15,26 +16,54 @@ use serde_json;
1516
/// Specifies which `rustfmt` to use.
1617
#[derive(Clone)]
1718
pub enum Rustfmt {
18-
/// `(path to external `rustfmt`, current working directory to spawn at)`
19-
External(PathBuf, PathBuf),
19+
/// Externally invoked `rustfmt` process.
20+
External { path: PathBuf, cwd: PathBuf },
2021
/// Statically linked `rustfmt`.
2122
Internal,
2223
}
2324

25+
/// Defines a formatting-related error.
26+
#[derive(Fail, Debug)]
27+
pub enum Error {
28+
/// Generic variant of `Error::Rustfmt` error.
29+
#[fail(display = "Formatting could not be completed.")]
30+
Failed,
31+
#[fail(display = "Could not format source code: {}", _0)]
32+
Rustfmt(rustfmt_nightly::ErrorKind),
33+
#[fail(display = "Encountered I/O error: {}", _0)]
34+
Io(std::io::Error),
35+
#[fail(display = "Config couldn't be converted to TOML for Rustfmt purposes: {}", _0)]
36+
ConfigTomlOutput(String),
37+
#[fail(display = "Formatted output is not valid UTF-8 source: {}", _0)]
38+
OutputNotUtf8(FromUtf8Error),
39+
}
40+
41+
impl From<std::io::Error> for Error {
42+
fn from(err: std::io::Error) -> Error {
43+
Error::Io(err)
44+
}
45+
}
46+
47+
impl From<FromUtf8Error> for Error {
48+
fn from(err: FromUtf8Error) -> Error {
49+
Error::OutputNotUtf8(err)
50+
}
51+
}
52+
2453
impl From<Option<(String, PathBuf)>> for Rustfmt {
2554
fn from(value: Option<(String, PathBuf)>) -> Rustfmt {
2655
match value {
27-
Some((path, cwd)) => Rustfmt::External(PathBuf::from(path), cwd),
56+
Some((path, cwd)) => Rustfmt::External { path: PathBuf::from(path), cwd },
2857
None => Rustfmt::Internal,
2958
}
3059
}
3160
}
3261

3362
impl Rustfmt {
34-
pub fn format(&self, input: String, cfg: Config) -> Result<String, String> {
63+
pub fn format(&self, input: String, cfg: Config) -> Result<String, Error> {
3564
match self {
3665
Rustfmt::Internal => format_internal(input, cfg),
37-
Rustfmt::External(path, cwd) => format_external(path, cwd, input, cfg),
66+
Rustfmt::External { path, cwd } => format_external(path, cwd, input, cfg),
3867
}
3968
}
4069
}
@@ -44,7 +73,7 @@ fn format_external(
4473
cwd: &PathBuf,
4574
input: String,
4675
cfg: Config,
47-
) -> Result<String, String> {
76+
) -> Result<String, Error> {
4877
let (_file_handle, config_path) = gen_config_file(&cfg)?;
4978
let args = rustfmt_args(&cfg, &config_path);
5079

@@ -54,25 +83,18 @@ fn format_external(
5483
.stdin(Stdio::piped())
5584
.stdout(Stdio::piped())
5685
.spawn()
57-
.map_err(|_| format!("Couldn't spawn `{}`", path.display()))?;
86+
.map_err(Error::Io)?;
5887

5988
{
60-
let stdin =
61-
rustfmt.stdin.as_mut().ok_or_else(|| "Failed to open rustfmt stdin".to_string())?;
62-
stdin
63-
.write_all(input.as_bytes())
64-
.map_err(|_| "Failed to pass input to rustfmt".to_string())?;
89+
let stdin = rustfmt.stdin.as_mut().unwrap(); // Safe because stdin is piped
90+
stdin.write_all(input.as_bytes())?;
6591
}
6692

67-
rustfmt.wait_with_output().map_err(|err| format!("Error running rustfmt: {}", err)).and_then(
68-
|out| {
69-
String::from_utf8(out.stdout)
70-
.map_err(|_| "Formatted code is not valid UTF-8".to_string())
71-
},
72-
)
93+
let output = rustfmt.wait_with_output()?;
94+
Ok(String::from_utf8(output.stdout)?)
7395
}
7496

75-
fn format_internal(input: String, config: Config) -> Result<String, String> {
97+
fn format_internal(input: String, config: Config) -> Result<String, Error> {
7698
let mut buf = Vec::<u8>::new();
7799

78100
{
@@ -85,37 +107,34 @@ fn format_internal(input: String, config: Config) -> Result<String, String> {
85107
if session.has_operational_errors() || session.has_parsing_errors() {
86108
debug!("reformat: format_input failed: has errors, report = {}", report);
87109

88-
return Err("Reformat failed to complete successfully".into());
110+
return Err(Error::Failed);
89111
}
90112
}
91113
Err(e) => {
92114
debug!("Reformat failed: {:?}", e);
93115

94-
return Err("Reformat failed to complete successfully".into());
116+
return Err(Error::Rustfmt(e));
95117
}
96118
}
97119
}
98120

99-
String::from_utf8(buf).map_err(|_| "Reformat output is not a valid UTF-8".into())
121+
Ok(String::from_utf8(buf)?)
100122
}
101123

102-
fn random_file() -> Result<(File, PathBuf), String> {
124+
fn random_file() -> Result<(File, PathBuf), Error> {
103125
const SUFFIX_LEN: usize = 10;
104126

105127
let suffix: String =
106128
thread_rng().sample_iter(&distributions::Alphanumeric).take(SUFFIX_LEN).collect();
107129
let path = temp_dir().join(suffix);
108130

109-
Ok(File::create(&path)
110-
.map(|file| (file, path))
111-
.map_err(|_| "Config file could not be created".to_string())?)
131+
Ok(File::create(&path).map(|file| (file, path))?)
112132
}
113133

114-
fn gen_config_file(config: &Config) -> Result<(File, PathBuf), String> {
134+
fn gen_config_file(config: &Config) -> Result<(File, PathBuf), Error> {
115135
let (mut file, path) = random_file()?;
116-
let toml = config.all_options().to_toml()?;
117-
file.write(toml.as_bytes())
118-
.map_err(|_| "Could not write config TOML file contents".to_string())?;
136+
let toml = config.all_options().to_toml().map_err(Error::ConfigTomlOutput)?;
137+
file.write_all(toml.as_bytes())?;
119138

120139
Ok((file, path))
121140
}

rls/src/actions/requests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,7 @@ fn reformat(
725725
let formatted_text = ctx
726726
.formatter()
727727
.format(input, config)
728-
.map_err(|msg| ResponseError::Message(ErrorCode::InternalError, msg))?;
728+
.map_err(|msg| ResponseError::Message(ErrorCode::InternalError, msg.to_string()))?;
729729

730730
// Note that we don't need to update the VFS, the client echos back the
731731
// change to us when it applies the returned `TextEdit`.

rls/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#![warn(clippy::all, rust_2018_idioms)]
1010
#![allow(clippy::cyclomatic_complexity, clippy::too_many_arguments, clippy::redundant_closure)]
1111

12+
#[macro_use]
13+
extern crate failure;
14+
1215
pub use rls_analysis::{AnalysisHost, Target};
1316
pub use rls_vfs::Vfs;
1417

0 commit comments

Comments
 (0)