mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Add methods to serialize Config to TOML.
Two different modes: - Serialize the full Config object. This is useful as `Config::default().to_toml()` to output a rustfmt.toml with defaults (#317). - Serialize only the options that have been accessed. This could be useful to output a minimal rustfmt.toml for a project. (If the default value of any unused config item changes, you'll then get the new default when you come to use it). This commit doesn't expose this anywhere - deciding a sensible CLI is a bit trickier. This commit also has very simple error reporting (Result<String, String>) - once the CLI is decided, a more sensible method of reporting errors might become obvious.
This commit is contained in:
parent
4d879662a9
commit
7a4955f705
@ -25,7 +25,7 @@ macro_rules! configuration_option_enum{
|
||||
$( $x ),+
|
||||
}
|
||||
|
||||
impl_enum_decodable!($e, $( $x ),+);
|
||||
impl_enum_serialize_and_deserialize!($e, $( $x ),+);
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,10 +247,10 @@ macro_rules! create_config {
|
||||
// Just like the Config struct but with each property wrapped
|
||||
// as Option<T>. This is used to parse a rustfmt.toml that doesn't
|
||||
// specity all properties of `Config`.
|
||||
// We first parse into `ParsedConfig`, then create a default `Config`
|
||||
// and overwrite the properties with corresponding values from `ParsedConfig`
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct ParsedConfig {
|
||||
// We first parse into `PartialConfig`, then create a default `Config`
|
||||
// and overwrite the properties with corresponding values from `PartialConfig`.
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
struct PartialConfig {
|
||||
$(pub $i: Option<$ty>),+
|
||||
}
|
||||
|
||||
@ -263,7 +263,7 @@ macro_rules! create_config {
|
||||
}
|
||||
)+
|
||||
|
||||
fn fill_from_parsed_config(mut self, parsed: ParsedConfig) -> Config {
|
||||
fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config {
|
||||
$(
|
||||
if let Some(val) = parsed.$i {
|
||||
self.$i = val;
|
||||
@ -306,6 +306,38 @@ macro_rules! create_config {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn used_to_toml(&self) -> Result<String, String> {
|
||||
let mut partial = PartialConfig {
|
||||
$(
|
||||
$i: if self.tracker.was_accessed(stringify!($i)) {
|
||||
Some(self.$i.clone())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)+
|
||||
};
|
||||
|
||||
// file_lines is special and can't be specified in toml.
|
||||
partial.file_lines = None;
|
||||
|
||||
toml::to_string(&partial)
|
||||
.map_err(|e| format!("Could not output config: {}", e.to_string()))
|
||||
}
|
||||
|
||||
pub fn to_toml(&self) -> Result<String, String> {
|
||||
let mut partial = PartialConfig {
|
||||
$(
|
||||
$i: Some(self.$i.clone()),
|
||||
)+
|
||||
};
|
||||
|
||||
// file_lines is special and can't be specified in toml.
|
||||
partial.file_lines = None;
|
||||
|
||||
toml::to_string(&partial)
|
||||
.map_err(|e| format!("Could not output config: {}", e.to_string()))
|
||||
}
|
||||
|
||||
pub fn override_value(&mut self, key: &str, val: &str)
|
||||
-> result::Result<(), Box<error::Error + Send + Sync>>
|
||||
{
|
||||
|
@ -216,6 +216,16 @@ impl<'de> ::serde::de::Deserialize<'de> for FileLines {
|
||||
}
|
||||
}
|
||||
|
||||
// We also want to avoid attempting to serialize a FileLines to toml. The
|
||||
// `Config` struct should ensure this impl is never reached.
|
||||
impl ::serde::ser::Serialize for FileLines {
|
||||
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error>
|
||||
where S: ::serde::ser::Serializer
|
||||
{
|
||||
panic!("FileLines cannot be serialized. This is a rustfmt bug.");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::Range;
|
||||
|
@ -35,7 +35,7 @@ pub enum ListTactic {
|
||||
Mixed,
|
||||
}
|
||||
|
||||
impl_enum_decodable!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed);
|
||||
impl_enum_serialize_and_deserialize!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed);
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub enum SeparatorTactic {
|
||||
@ -44,7 +44,7 @@ pub enum SeparatorTactic {
|
||||
Vertical,
|
||||
}
|
||||
|
||||
impl_enum_decodable!(SeparatorTactic, Always, Never, Vertical);
|
||||
impl_enum_serialize_and_deserialize!(SeparatorTactic, Always, Never, Vertical);
|
||||
|
||||
impl SeparatorTactic {
|
||||
pub fn from_bool(b: bool) -> SeparatorTactic {
|
||||
|
23
src/utils.rs
23
src/utils.rs
@ -189,10 +189,29 @@ pub fn trim_newlines(input: &str) -> &str {
|
||||
}
|
||||
}
|
||||
|
||||
// Macro for deriving implementations of Decodable for enums
|
||||
// Macro for deriving implementations of Serialize/Deserialize for enums
|
||||
#[macro_export]
|
||||
macro_rules! impl_enum_decodable {
|
||||
macro_rules! impl_enum_serialize_and_deserialize {
|
||||
( $e:ident, $( $x:ident ),* ) => {
|
||||
impl ::serde::ser::Serialize for $e {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: ::serde::ser::Serializer
|
||||
{
|
||||
use serde::ser::Error;
|
||||
|
||||
// We don't know whether the user of the macro has given us all options.
|
||||
#[allow(unreachable_patterns)]
|
||||
match *self {
|
||||
$(
|
||||
$e::$x => serializer.serialize_str(stringify!($x)),
|
||||
)*
|
||||
_ => {
|
||||
Err(S::Error::custom(format!("Cannot serialize {:?}", self)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> ::serde::de::Deserialize<'de> for $e {
|
||||
fn deserialize<D>(d: D) -> Result<Self, D::Error>
|
||||
where D: ::serde::Deserializer<'de> {
|
||||
|
Loading…
Reference in New Issue
Block a user