From 6af096851124a515fa13e8cf07c646b70fce41d9 Mon Sep 17 00:00:00 2001
From: topecongiro <seuchida@gmail.com>
Date: Sat, 1 Apr 2017 00:45:02 +0900
Subject: [PATCH] Change return type of 'from_toml' from 'Config' to
 'Result<Config>'

Closes #1426.
---
 src/bin/rustfmt.rs | 15 ++++++++-------
 src/config.rs      | 24 +++++++++++++-----------
 tests/system.rs    |  2 +-
 3 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs
index af6996613bf..c60201bbb25 100644
--- a/src/bin/rustfmt.rs
+++ b/src/bin/rustfmt.rs
@@ -149,7 +149,10 @@ fn resolve_config(dir: &Path) -> FmtResult<(Config, Option<PathBuf>)> {
     let mut file = try!(File::open(&path));
     let mut toml = String::new();
     try!(file.read_to_string(&mut toml));
-    Ok((Config::from_toml(&toml), Some(path)))
+    match Config::from_toml(&toml) {
+        Ok(cfg) => Ok((cfg, Some(path))),
+        Err(err) => Err(FmtError::from(err)),
+    }
 }
 
 /// read the given config file path recursively if present else read the project file path
@@ -211,8 +214,8 @@ fn execute(opts: &Options) -> FmtResult<Summary> {
         }
         Operation::Stdin { input, config_path } => {
             // try to read config from local directory
-            let (mut config, _) = match_cli_path_or_file(config_path, &env::current_dir().unwrap())
-                .expect("Error resolving config");
+            let (mut config, _) = match_cli_path_or_file(config_path,
+                                                         &env::current_dir().unwrap())?;
 
             // write_mode is always Plain for Stdin.
             config.write_mode = WriteMode::Plain;
@@ -232,8 +235,7 @@ fn execute(opts: &Options) -> FmtResult<Summary> {
             let mut path = None;
             // Load the config path file if provided
             if let Some(config_file) = config_path {
-                let (cfg_tmp, path_tmp) = resolve_config(config_file.as_ref())
-                    .expect(&format!("Error resolving config for {:?}", config_file));
+                let (cfg_tmp, path_tmp) = resolve_config(config_file.as_ref())?;
                 config = cfg_tmp;
                 path = path_tmp;
             };
@@ -248,8 +250,7 @@ fn execute(opts: &Options) -> FmtResult<Summary> {
             for file in files {
                 // Check the file directory if the config-path could not be read or not provided
                 if path.is_none() {
-                    let (config_tmp, path_tmp) = resolve_config(file.parent().unwrap())
-                        .expect(&format!("Error resolving config for {}", file.display()));
+                    let (config_tmp, path_tmp) = resolve_config(file.parent().unwrap())?;
                     if options.verbose {
                         if let Some(path) = path_tmp.as_ref() {
                             println!("Using rustfmt config file {} for {}",
diff --git a/src/config.rs b/src/config.rs
index 9a554659e83..21ab6cd5447 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -12,7 +12,6 @@ extern crate toml;
 
 use file_lines::FileLines;
 use lists::{SeparatorTactic, ListTactic};
-use std::io::Write;
 
 macro_rules! configuration_option_enum{
     ($e:ident: $( $x:ident ),+ $(,)*) => {
@@ -237,26 +236,29 @@ macro_rules! create_config {
                 self
             }
 
-            pub fn from_toml(toml: &str) -> Config {
+            pub fn from_toml(toml: &str) -> Result<Config, String> {
                 let parsed: toml::Value = toml.parse().expect("Could not parse TOML");
+                let mut err: String = String::new();
                 for (key, _) in parsed.as_table().expect("Parsed config was not table") {
                     match &**key {
                         $(
                             stringify!($i) => (),
                         )+
-                        _ => msg!("Warning: Unused configuration option {}", key),
+                        _ => {
+                            let msg = &format!("Warning: Unknown configuration option `{}`\n", key);
+                            err.push_str(msg)
+                        }
                     }
                 }
-                let parsed_config:ParsedConfig = match toml::decode(parsed) {
-                    Some(decoded) => decoded,
+                match toml::decode(parsed) {
+                    Some(parsed_config) =>
+                        Ok(Config::default().fill_from_parsed_config(parsed_config)),
                     None => {
-                        msg!("Decoding config file failed. Config:\n{}", toml);
-                        let parsed: toml::Value = toml.parse().expect("Could not parse TOML");
-                        msg!("\n\nParsed:\n{:?}", parsed);
-                        panic!();
+                        err.push_str("Error: Decoding config file failed. ");
+                        err.push_str("Please check your config file.\n");
+                        Err(err)
                     }
-                };
-                Config::default().fill_from_parsed_config(parsed_config)
+                }
             }
 
             pub fn override_value(&mut self, key: &str, val: &str) {
diff --git a/tests/system.rs b/tests/system.rs
index 7eeea235679..0d7c47feb32 100644
--- a/tests/system.rs
+++ b/tests/system.rs
@@ -285,7 +285,7 @@ fn get_config(config_file: Option<&str>) -> Config {
         .read_to_string(&mut def_config)
         .expect("Couldn't read config");
 
-    Config::from_toml(&def_config)
+    Config::from_toml(&def_config).expect("Invalid toml")
 }
 
 // Reads significant comments of the form: // rustfmt-key: value