From: mcarton Date: Sun, 6 Mar 2016 14:17:51 +0000 (+0100) Subject: mv src/conf.rs src/utils X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=d118b27abb50fef41f7a9510aa9e3741ac036370;p=rust.git mv src/conf.rs src/utils --- diff --git a/src/conf.rs b/src/conf.rs deleted file mode 100644 index 93caa1edca3..00000000000 --- a/src/conf.rs +++ /dev/null @@ -1,189 +0,0 @@ -use std::{fmt, fs, io}; -use std::io::Read; -use syntax::{ast, codemap, ptr}; -use syntax::parse::token; -use toml; - -/// Get the configuration file from arguments. -pub fn conf_file(args: &[ptr::P]) -> Result, (&'static str, codemap::Span)> { - for arg in args { - match arg.node { - ast::MetaItemKind::Word(ref name) | ast::MetaItemKind::List(ref name, _) => { - if name == &"conf_file" { - return Err(("`conf_file` must be a named value", arg.span)); - } - } - ast::MetaItemKind::NameValue(ref name, ref value) => { - if name == &"conf_file" { - return if let ast::LitKind::Str(ref file, _) = value.node { - Ok(Some(file.clone())) - } else { - Err(("`conf_file` value must be a string", value.span)) - }; - } - } - } - } - - Ok(None) -} - -/// Error from reading a configuration file. -#[derive(Debug)] -pub enum ConfError { - IoError(io::Error), - TomlError(Vec), - TypeError(&'static str, &'static str, &'static str), - UnknownKey(String), -} - -impl fmt::Display for ConfError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - ConfError::IoError(ref err) => err.fmt(f), - ConfError::TomlError(ref errs) => { - let mut first = true; - for err in errs { - if !first { - try!(", ".fmt(f)); - first = false; - } - - try!(err.fmt(f)); - } - - Ok(()) - } - ConfError::TypeError(ref key, ref expected, ref got) => { - write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) - } - ConfError::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), - } - } -} - -impl From for ConfError { - fn from(e: io::Error) -> Self { - ConfError::IoError(e) - } -} - -macro_rules! define_Conf { - ($(#[$doc: meta] ($toml_name: tt, $rust_name: ident, $default: expr => $($ty: tt)+),)+) => { - /// Type used to store lint configuration. - pub struct Conf { - $(#[$doc] pub $rust_name: define_Conf!(TY $($ty)+),)+ - } - - impl Default for Conf { - fn default() -> Conf { - Conf { - $($rust_name: define_Conf!(DEFAULT $($ty)+, $default),)+ - } - } - } - - impl Conf { - /// Set the property `name` (which must be the `toml` name) to the given value - #[allow(cast_sign_loss)] - fn set(&mut self, name: String, value: toml::Value) -> Result<(), ConfError> { - match name.as_str() { - $( - define_Conf!(PAT $toml_name) => { - if let Some(value) = define_Conf!(CONV $($ty)+, value) { - self.$rust_name = value; - } - else { - return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name), - stringify!($($ty)+), - value.type_str())); - } - }, - )+ - "third-party" => { - // for external tools such as clippy-service - return Ok(()); - } - _ => { - return Err(ConfError::UnknownKey(name)); - } - } - - Ok(()) - } - } - }; - - // hack to convert tts - (PAT $pat: pat) => { $pat }; - (EXPR $e: expr) => { $e }; - (TY $ty: ty) => { $ty }; - - // how to read the value? - (CONV i64, $value: expr) => { $value.as_integer() }; - (CONV u64, $value: expr) => { $value.as_integer().iter().filter_map(|&i| if i >= 0 { Some(i as u64) } else { None }).next() }; - (CONV String, $value: expr) => { $value.as_str().map(Into::into) }; - (CONV Vec, $value: expr) => {{ - let slice = $value.as_slice(); - - if let Some(slice) = slice { - if slice.iter().any(|v| v.as_str().is_none()) { - None - } - else { - Some(slice.iter().map(|v| v.as_str().unwrap_or_else(|| unreachable!()).to_owned()).collect()) - } - } - else { - None - } - }}; - - // provide a nicer syntax to declare the default value of `Vec` variables - (DEFAULT Vec, $e: expr) => { $e.iter().map(|&e| e.to_owned()).collect() }; - (DEFAULT $ty: ty, $e: expr) => { $e }; -} - -define_Conf! { - /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about - ("blacklisted-names", blacklisted_names, ["foo", "bar", "baz"] => Vec), - /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have - ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), - /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have - ("too-many-arguments-threshold", too_many_arguments_threshold, 6 => u64), - /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have - ("type-complexity-threshold", type_complexity_threshold, 250 => u64), -} - -/// Read the `toml` configuration file. The function will ignore “File not found” errors iif -/// `!must_exist`, in which case, it will return the default configuration. -pub fn read_conf(path: &str, must_exist: bool) -> Result { - let mut conf = Conf::default(); - - let file = match fs::File::open(path) { - Ok(mut file) => { - let mut buf = String::new(); - try!(file.read_to_string(&mut buf)); - buf - } - Err(ref err) if !must_exist && err.kind() == io::ErrorKind::NotFound => { - return Ok(conf); - } - Err(err) => { - return Err(err.into()); - } - }; - - let mut parser = toml::Parser::new(&file); - let toml = if let Some(toml) = parser.parse() { - toml - } else { - return Err(ConfError::TomlError(parser.errors)); - }; - - for (key, value) in toml { - try!(conf.set(key, value)); - } - - Ok(conf) -} diff --git a/src/lib.rs b/src/lib.rs index 66ae815d7e0..a7fe2c1aab3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,7 +38,6 @@ fn main() { use rustc_plugin::Registry; -mod conf; pub mod consts; #[macro_use] pub mod utils; @@ -112,12 +111,12 @@ mod reexport { #[plugin_registrar] #[cfg_attr(rustfmt, rustfmt_skip)] pub fn plugin_registrar(reg: &mut Registry) { - let conferr = match conf::conf_file(reg.args()) { + let conferr = match utils::conf::conf_file(reg.args()) { Ok(Some(file_name)) => { - conf::read_conf(&file_name, true) + utils::conf::read_conf(&file_name, true) } Ok(None) => { - conf::read_conf("Clippy.toml", false) + utils::conf::read_conf("Clippy.toml", false) } Err((err, span)) => { reg.sess.struct_span_err(span, err).emit(); diff --git a/src/utils/conf.rs b/src/utils/conf.rs new file mode 100644 index 00000000000..93caa1edca3 --- /dev/null +++ b/src/utils/conf.rs @@ -0,0 +1,189 @@ +use std::{fmt, fs, io}; +use std::io::Read; +use syntax::{ast, codemap, ptr}; +use syntax::parse::token; +use toml; + +/// Get the configuration file from arguments. +pub fn conf_file(args: &[ptr::P]) -> Result, (&'static str, codemap::Span)> { + for arg in args { + match arg.node { + ast::MetaItemKind::Word(ref name) | ast::MetaItemKind::List(ref name, _) => { + if name == &"conf_file" { + return Err(("`conf_file` must be a named value", arg.span)); + } + } + ast::MetaItemKind::NameValue(ref name, ref value) => { + if name == &"conf_file" { + return if let ast::LitKind::Str(ref file, _) = value.node { + Ok(Some(file.clone())) + } else { + Err(("`conf_file` value must be a string", value.span)) + }; + } + } + } + } + + Ok(None) +} + +/// Error from reading a configuration file. +#[derive(Debug)] +pub enum ConfError { + IoError(io::Error), + TomlError(Vec), + TypeError(&'static str, &'static str, &'static str), + UnknownKey(String), +} + +impl fmt::Display for ConfError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + ConfError::IoError(ref err) => err.fmt(f), + ConfError::TomlError(ref errs) => { + let mut first = true; + for err in errs { + if !first { + try!(", ".fmt(f)); + first = false; + } + + try!(err.fmt(f)); + } + + Ok(()) + } + ConfError::TypeError(ref key, ref expected, ref got) => { + write!(f, "`{}` is expected to be a `{}` but is a `{}`", key, expected, got) + } + ConfError::UnknownKey(ref key) => write!(f, "unknown key `{}`", key), + } + } +} + +impl From for ConfError { + fn from(e: io::Error) -> Self { + ConfError::IoError(e) + } +} + +macro_rules! define_Conf { + ($(#[$doc: meta] ($toml_name: tt, $rust_name: ident, $default: expr => $($ty: tt)+),)+) => { + /// Type used to store lint configuration. + pub struct Conf { + $(#[$doc] pub $rust_name: define_Conf!(TY $($ty)+),)+ + } + + impl Default for Conf { + fn default() -> Conf { + Conf { + $($rust_name: define_Conf!(DEFAULT $($ty)+, $default),)+ + } + } + } + + impl Conf { + /// Set the property `name` (which must be the `toml` name) to the given value + #[allow(cast_sign_loss)] + fn set(&mut self, name: String, value: toml::Value) -> Result<(), ConfError> { + match name.as_str() { + $( + define_Conf!(PAT $toml_name) => { + if let Some(value) = define_Conf!(CONV $($ty)+, value) { + self.$rust_name = value; + } + else { + return Err(ConfError::TypeError(define_Conf!(EXPR $toml_name), + stringify!($($ty)+), + value.type_str())); + } + }, + )+ + "third-party" => { + // for external tools such as clippy-service + return Ok(()); + } + _ => { + return Err(ConfError::UnknownKey(name)); + } + } + + Ok(()) + } + } + }; + + // hack to convert tts + (PAT $pat: pat) => { $pat }; + (EXPR $e: expr) => { $e }; + (TY $ty: ty) => { $ty }; + + // how to read the value? + (CONV i64, $value: expr) => { $value.as_integer() }; + (CONV u64, $value: expr) => { $value.as_integer().iter().filter_map(|&i| if i >= 0 { Some(i as u64) } else { None }).next() }; + (CONV String, $value: expr) => { $value.as_str().map(Into::into) }; + (CONV Vec, $value: expr) => {{ + let slice = $value.as_slice(); + + if let Some(slice) = slice { + if slice.iter().any(|v| v.as_str().is_none()) { + None + } + else { + Some(slice.iter().map(|v| v.as_str().unwrap_or_else(|| unreachable!()).to_owned()).collect()) + } + } + else { + None + } + }}; + + // provide a nicer syntax to declare the default value of `Vec` variables + (DEFAULT Vec, $e: expr) => { $e.iter().map(|&e| e.to_owned()).collect() }; + (DEFAULT $ty: ty, $e: expr) => { $e }; +} + +define_Conf! { + /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about + ("blacklisted-names", blacklisted_names, ["foo", "bar", "baz"] => Vec), + /// Lint: CYCLOMATIC_COMPLEXITY. The maximum cyclomatic complexity a function can have + ("cyclomatic-complexity-threshold", cyclomatic_complexity_threshold, 25 => u64), + /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have + ("too-many-arguments-threshold", too_many_arguments_threshold, 6 => u64), + /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have + ("type-complexity-threshold", type_complexity_threshold, 250 => u64), +} + +/// Read the `toml` configuration file. The function will ignore “File not found” errors iif +/// `!must_exist`, in which case, it will return the default configuration. +pub fn read_conf(path: &str, must_exist: bool) -> Result { + let mut conf = Conf::default(); + + let file = match fs::File::open(path) { + Ok(mut file) => { + let mut buf = String::new(); + try!(file.read_to_string(&mut buf)); + buf + } + Err(ref err) if !must_exist && err.kind() == io::ErrorKind::NotFound => { + return Ok(conf); + } + Err(err) => { + return Err(err.into()); + } + }; + + let mut parser = toml::Parser::new(&file); + let toml = if let Some(toml) = parser.parse() { + toml + } else { + return Err(ConfError::TomlError(parser.errors)); + }; + + for (key, value) in toml { + try!(conf.set(key, value)); + } + + Ok(conf) +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 625e8da197d..feeb70126ea 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -14,6 +14,7 @@ use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; +pub mod conf; mod hir; pub use self::hir::{SpanlessEq, SpanlessHash}; pub type MethodArgs = HirVec>;