diff --git a/parser/.travis.yml b/parser/.travis.yml index 5e1e170..627e527 100644 --- a/parser/.travis.yml +++ b/parser/.travis.yml @@ -7,5 +7,8 @@ rust: env: global: - secure: ZUcdcbS8xbpdII9FSPx7VtoVhEkJhWL2Hb75tDlKDHNhfXqmt1NyB9q/2qXJ5Ulp4MnYXwsI8LsDloR6gvdB4xElay3smuF/neGvMjrqcB15/2p0MSQ+kZjMsNB6mlb5kAlm8ahduXIscppmw/V+m5hn3Vo+RQz/Ng+pzv0nc8KEXPMYrfRFg+a7FaeIbRbb8ir9EfflUSqArLq2hbi2WdhM3hFMcCIAUt6DD4x5ubjEg60OnIof5FDu0mXMXzQvUfHWOeYnsNcD/DLyDnm6FuQEzk37M4EB8op2SdBUeQMQ5abR3i2rd//DZpbTTEjud0PseWohGAwTwL2aoFrqs7uYQMx+vcGlOzAyDUm4VemVUa3F2BECdzU5BiujcKOITJEVUYWongld93arQq34FuXG/TO/T1XrerxfG6LTkTkKS5Vz7W8z6Rloa99WrQLJg1ZJP6itEU7G7KsDFVgRhsg7rz4/dV/2+cV4UvIwd4HlGXKCFlH0SClqvM3/7i/qqCD0689SJW6Zip+ly38MXlGy2s/AmReEasXvFer9JkOEIuPa8QTBNAjDlw7bWXi6neQWBIZU1VhZcSssnrVmEFN8fNklShzpw5DyKCv8jPTx2O6Dw8B/LgIK8uo+eaTXiO6zz/T1c/qEdsYslvxPA2D3F+ONpPU7238ykT4eRog= +script: + - cargo build --features clippy --verbose + - cargo test --verbose after_script: - curl http://www.rust-ci.org/artifacts/put?t=$RUSTCI_TOKEN | sh diff --git a/parser/Cargo.toml b/parser/Cargo.toml index d427e4b..46d8c7a 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -7,3 +7,6 @@ documentation = "http://chyh1990.github.io/yaml-rust/doc/yaml_rust/" license = "MIT/Apache-2.0" description = "The missing YAML 1.2 parser for rust" repository = "https://github.com/chyh1990/yaml-rust" + +[dependencies] +clippy = { version = "^0.*", optional = true } diff --git a/parser/src/emitter.rs b/parser/src/emitter.rs index 8810c95..fe9a6e1 100644 --- a/parser/src/emitter.rs +++ b/parser/src/emitter.rs @@ -114,8 +114,8 @@ impl<'a> YamlEmitter<'a> { } fn emit_node(&mut self, node: &Yaml) -> EmitResult { - match node { - &Yaml::Array(ref v) => { + match *node { + Yaml::Array(ref v) => { if v.is_empty() { try!(write!(self.writer, "[]")); Ok(()) @@ -124,21 +124,19 @@ impl<'a> YamlEmitter<'a> { try!(write!(self.writer, "\n")); } self.level += 1; - let mut cnt = 0usize; - for x in v { + for (cnt, x) in v.iter().enumerate() { + if cnt > 0 { + try!(write!(self.writer, "\n")); + } try!(self.write_indent()); try!(write!(self.writer, "- ")); try!(self.emit_node(x)); - cnt += 1; - if cnt < v.len() { - try!(write!(self.writer, "\n")); - } } self.level -= 1; Ok(()) } }, - &Yaml::Hash(ref h) => { + Yaml::Hash(ref h) => { if h.is_empty() { try!(self.writer.write_str("{}")); Ok(()) @@ -147,32 +145,30 @@ impl<'a> YamlEmitter<'a> { try!(write!(self.writer, "\n")); } self.level += 1; - let mut cnt = 0usize; - for (k, v) in h { + for (cnt, (k, v)) in h.iter().enumerate() { + if cnt > 0 { + try!(write!(self.writer, "\n")); + } try!(self.write_indent()); - match k { + match *k { // complex key is not supported - &Yaml::Array(_) | &Yaml::Hash(_) => { + Yaml::Array(_) | Yaml::Hash(_) => { return Err(EmitError::BadHashmapKey); }, _ => { try!(self.emit_node(k)); } } try!(write!(self.writer, ": ")); try!(self.emit_node(v)); - cnt += 1; - if cnt < h.len() { - try!(write!(self.writer, "\n")); - } } self.level -= 1; Ok(()) } }, - &Yaml::String(ref v) => { + Yaml::String(ref v) => { try!(escape_str(self.writer, v)); Ok(()) }, - &Yaml::Boolean(v) => { + Yaml::Boolean(v) => { if v { try!(self.writer.write_str("true")); } else { @@ -180,15 +176,15 @@ impl<'a> YamlEmitter<'a> { } Ok(()) }, - &Yaml::Integer(v) => { + Yaml::Integer(v) => { try!(write!(self.writer, "{}", v)); Ok(()) }, - &Yaml::Real(ref v) => { + Yaml::Real(ref v) => { try!(write!(self.writer, "{}", v)); Ok(()) }, - &Yaml::Null | &Yaml::BadValue => { + Yaml::Null | Yaml::BadValue => { try!(write!(self.writer, "~")); Ok(()) }, diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 1cba925..dc66adc 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -36,6 +36,12 @@ //! //! ``` +#![cfg_attr(feature="clippy", feature(plugin))] +#![cfg_attr(feature="clippy", plugin(clippy))] +#![cfg_attr(feature="clippy", deny(clippy))] +#![cfg_attr(feature="clippy", warn(cyclomatic_complexity))] +#![cfg_attr(feature="clippy", allow(match_same_arms))] + pub mod yaml; pub mod scanner; pub mod parser; @@ -89,7 +95,7 @@ mod tests { emitter.dump(doc).unwrap(); } - assert!(writer.len() > 0); + assert!(!writer.is_empty()); } fn try_fail(s: &str) -> Result, ScanError> { diff --git a/parser/src/parser.rs b/parser/src/parser.rs index a6cdf73..65924d7 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -55,11 +55,11 @@ pub enum Event { impl Event { fn empty_scalar() -> Event { // a null scalar - Event::Scalar("~".to_string(), TScalarStyle::Plain, 0, None) + Event::Scalar("~".to_owned(), TScalarStyle::Plain, 0, None) } fn empty_scalar_with_anchor(anchor: usize, tag: TokenType) -> Event { - Event::Scalar("".to_string(), TScalarStyle::Plain, anchor, Some(tag)) + Event::Scalar("".to_owned(), TScalarStyle::Plain, anchor, Some(tag)) } } @@ -179,10 +179,7 @@ impl> Parser { fn load_node(&mut self, first_ev: &Event, recv: &mut R) -> Result<(), ScanError> { match *first_ev { - Event::Alias(..) => { - Ok(()) - }, - Event::Scalar(..) => { + Event::Alias(..) | Event::Scalar(..) => { Ok(()) }, Event::SequenceStart(_) => { @@ -275,7 +272,7 @@ impl> Parser { self.skip(); Ok(Event::StreamStart) }, - _ => return Err(ScanError::new(tok.0, + _ => Err(ScanError::new(tok.0, "did not find expected ")), } } @@ -283,14 +280,9 @@ impl> Parser { fn document_start(&mut self, implicit: bool) -> ParseResult { let mut tok = try!(self.peek()); if !implicit { - loop { - match tok.1 { - TokenType::DocumentEnd => { - self.skip(); - tok = try!(self.peek()); - }, - _ => break - } + while let TokenType::DocumentEnd = tok.1 { + self.skip(); + tok = try!(self.peek()); } } @@ -298,7 +290,7 @@ impl> Parser { TokenType::StreamEnd => { self.state = State::End; self.skip(); - return Ok(Event::StreamEnd); + Ok(Event::StreamEnd) }, TokenType::VersionDirective(..) | TokenType::TagDirective(..) @@ -376,12 +368,9 @@ impl> Parser { let tok = try!(self.peek()); let _start_mark = tok.0; - match tok.1 { - TokenType::DocumentEnd => { - self.skip(); - _implicit = false; - } - _ => {} + if let TokenType::DocumentEnd = tok.1 { + self.skip(); + _implicit = false; } // TODO tag handling @@ -389,7 +378,7 @@ impl> Parser { Ok(Event::DocumentEnd) } - fn register_anchor(&mut self, name: &String, _: &Marker) -> Result { + fn register_anchor(&mut self, name: &str, _: &Marker) -> Result { // anchors can be overrided/reused // if self.anchors.contains_key(name) { // return Err(ScanError::new(*mark, @@ -397,7 +386,7 @@ impl> Parser { // } let new_id = self.anchor_id; self.anchor_id += 1; - self.anchors.insert(name.clone(), new_id); + self.anchors.insert(name.to_owned(), new_id); Ok(new_id) } diff --git a/parser/src/scanner.rs b/parser/src/scanner.rs index 16c3b61..d0b5e2b 100644 --- a/parser/src/scanner.rs +++ b/parser/src/scanner.rs @@ -45,7 +45,7 @@ impl ScanError { pub fn new(loc: Marker, info: &str) -> ScanError { ScanError { mark: loc, - info: info.to_string() + info: info.to_owned() } } } @@ -233,7 +233,7 @@ impl> Scanner { } } - #[inline(always)] + #[inline] fn lookahead(&mut self, count: usize) { if self.buffer.len() >= count { return; @@ -386,7 +386,7 @@ impl> Scanner { // plain scalar '-' if !is_blankz(nc) => self.fetch_plain_scalar(), ':' | '?' if !is_blankz(nc) && self.flow_level == 0 => self.fetch_plain_scalar(), - '%' | '@' | '`' => return Err(ScanError::new(self.mark, + '%' | '@' | '`' => Err(ScanError::new(self.mark, &format!("unexpected character: `{}'", c))), _ => self.fetch_plain_scalar(), } @@ -404,9 +404,8 @@ impl> Scanner { self.token_available = false; self.tokens_parsed += 1; - match t.1 { - TokenType::StreamEnd => self.stream_end_produced = true, - _ => {} + if let TokenType::StreamEnd = t.1 { + self.stream_end_produced = true; } Ok(Some(t)) } @@ -697,12 +696,12 @@ impl> Scanner { suffix = try!(self.scan_tag_uri(false, secondary, &String::new(), &start_mark)); } else { suffix = try!(self.scan_tag_uri(false, false, &handle, &start_mark)); - handle = "!".to_string(); + handle = "!".to_owned(); // A special case: the '!' tag. Set the handle to '' and the // suffix to '!'. - if suffix.len() == 0 { + if suffix.is_empty() { handle.clear(); - suffix = "!".to_string(); + suffix = "!".to_owned(); } } } @@ -739,20 +738,18 @@ impl> Scanner { if self.ch() == '!' { string.push(self.ch()); self.skip(); - } else { + } else if directive && string != "!" { // It's either the '!' tag or not really a tag handle. If it's a %TAG // directive, it's an error. If it's a tag token, it must be a part of // URI. - if directive && string != "!" { - return Err(ScanError::new(*mark, - "while parsing a tag directive, did not find expected '!'")); - } + return Err(ScanError::new(*mark, + "while parsing a tag directive, did not find expected '!'")); } Ok(string) } fn scan_tag_uri(&mut self, directive: bool, _is_secondary: bool, - head: &String, mark: &Marker) -> Result { + head: &str, mark: &Marker) -> Result { let mut length = head.len(); let mut string = String::new(); @@ -1588,10 +1585,8 @@ impl> Scanner { fn remove_simple_key(&mut self) -> ScanResult { let last = self.simple_keys.last_mut().unwrap(); - if last.possible { - if last.required { - return Err(ScanError::new(self.mark, "simple key expected")); - } + if last.possible && last.required { + return Err(ScanError::new(self.mark, "simple key expected")); } last.possible = false; diff --git a/parser/src/yaml.rs b/parser/src/yaml.rs index d63e357..6db2a1b 100644 --- a/parser/src/yaml.rs +++ b/parser/src/yaml.rs @@ -94,46 +94,43 @@ impl EventReceiver for YamlLoader { Event::Scalar(ref v, style, aid, ref tag) => { let node = if style != TScalarStyle::Plain { Yaml::String(v.clone()) - } else { - match tag { - &Some(TokenType::Tag(ref handle, ref suffix)) => { - // XXX tag:yaml.org,2002: - if handle == "!!" { - match suffix.as_ref() { - "bool" => { - // "true" or "false" - match v.parse::() { - Err(_) => Yaml::BadValue, - Ok(v) => Yaml::Boolean(v) - } - }, - "int" => { - match v.parse::() { - Err(_) => Yaml::BadValue, - Ok(v) => Yaml::Integer(v) - } - }, - "float" => { - match v.parse::() { - Err(_) => Yaml::BadValue, - Ok(_) => Yaml::Real(v.clone()) - } - }, - "null" => { - match v.as_ref() { - "~" | "null" => Yaml::Null, - _ => Yaml::BadValue, - } - } - _ => Yaml::String(v.clone()), + } else if let Some(TokenType::Tag(ref handle, ref suffix)) = *tag { + // XXX tag:yaml.org,2002: + if handle == "!!" { + match suffix.as_ref() { + "bool" => { + // "true" or "false" + match v.parse::() { + Err(_) => Yaml::BadValue, + Ok(v) => Yaml::Boolean(v) + } + }, + "int" => { + match v.parse::() { + Err(_) => Yaml::BadValue, + Ok(v) => Yaml::Integer(v) + } + }, + "float" => { + match v.parse::() { + Err(_) => Yaml::BadValue, + Ok(_) => Yaml::Real(v.clone()) + } + }, + "null" => { + match v.as_ref() { + "~" | "null" => Yaml::Null, + _ => Yaml::BadValue, } - } else { - Yaml::String(v.clone()) } - }, - // Datatype is not specified, or unrecognized - _ => { Yaml::from_str(v.as_ref()) } + _ => Yaml::String(v.clone()), + } + } else { + Yaml::String(v.clone()) } + } else { + // Datatype is not specified, or unrecognized + Yaml::from_str(v.as_ref()) }; self.insert_new_node((node, aid)); @@ -245,7 +242,12 @@ impl Yaml { _ => None } } +} +#[cfg_attr(feature="clippy", allow(should_implement_trait))] +impl Yaml { + // Not implementing FromStr because there is no possibility of Error. + // This function falls back to Yaml::String if nothing else matches. pub fn from_str(v: &str) -> Yaml { if v.starts_with("0x") { let n = i64::from_str_radix(&v[2..], 16); @@ -259,8 +261,8 @@ impl Yaml { return Yaml::Integer(n.unwrap()); } } - if v.starts_with("+") && v[1..].parse::().is_ok() { - return Yaml::Integer(v[1..].parse::().unwrap()); + if v.starts_with('+') && v[1..].parse::().is_ok() { + return Yaml::Integer(v[1..].parse::().unwrap()); } match v { "~" | "null" => Yaml::Null, @@ -268,8 +270,8 @@ impl Yaml { "false" => Yaml::Boolean(false), _ if v.parse::().is_ok() => Yaml::Integer(v.parse::().unwrap()), // try parsing as f64 - _ if v.parse::().is_ok() => Yaml::Real(v.to_string()), - _ => Yaml::String(v.to_string()) + _ if v.parse::().is_ok() => Yaml::Real(v.to_owned()), + _ => Yaml::String(v.to_owned()) } } } @@ -279,7 +281,7 @@ impl<'a> Index<&'a str> for Yaml { type Output = Yaml; fn index(&self, idx: &'a str) -> &Yaml { - let key = Yaml::String(idx.to_string()); + let key = Yaml::String(idx.to_owned()); match self.as_hash() { Some(h) => h.get(&key).unwrap_or(&BAD_VALUE), None => &BAD_VALUE @@ -333,7 +335,7 @@ a4: a5: 'single_quoted' a6: \"double_quoted\" a7: 你好 -".to_string(); +".to_owned(); let out = YamlLoader::load_from_str(&s).unwrap(); let doc = &out[0]; assert_eq!(doc["a7"].as_str().unwrap(), "你好");