diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..d1f040a2 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 4 + +[*.md] +trim_trailing_whitespace = false diff --git a/Cargo.toml b/Cargo.toml index 036a709c..095f5e3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,8 @@ regex = "^0.2.1" lazy_static = "^0.2.4" unicode_categories = "^0.1.1" clap = { version = "^2.22.2", optional = true } +clippy = { version = "^0.0.123", optional = true } [features] default = ["clap"] +dev = ["clap", "clippy"] diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..7bcfcb7d --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +format_strings = false +reorder_imports = true diff --git a/src/cm.rs b/src/cm.rs index 867b99c7..e71070ad 100644 --- a/src/cm.rs +++ b/src/cm.rs @@ -44,11 +44,11 @@ enum Escaping { impl<'a, 'o> Write for CommonMarkFormatter<'a, 'o> { fn write(&mut self, buf: &[u8]) -> std::io::Result { self.output(buf, false, Escaping::Literal); - std::result::Result::Ok(buf.len()) + Ok(buf.len()) } fn flush(&mut self) -> std::io::Result<()> { - std::result::Result::Ok(()) + Ok(()) } } @@ -282,7 +282,7 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> { } NodeValue::Item(..) => { let parent = match node.parent().unwrap().data.borrow().value { - NodeValue::List(ref nl) => nl.clone(), + NodeValue::List(ref nl) => *nl, _ => unreachable!(), }; @@ -492,7 +492,7 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> { if is_autolink(node, nl) { if entering { write!(self, "<").unwrap(); - if &&nl.url[..7] == &"mailto:" { + if &nl.url[..7] == "mailto:" { self.write_all(nl.url[7..].as_bytes()).unwrap(); } else { self.write_all(nl.url.as_bytes()).unwrap(); @@ -565,11 +565,11 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> { for a in alignments { write!(self, " {} |", - match a { - &TableAlignment::Left => ":--", - &TableAlignment::Center => ":-:", - &TableAlignment::Right => "--:", - &TableAlignment::None => "---", + match *a { + TableAlignment::Left => ":--", + TableAlignment::Center => ":-:", + TableAlignment::Right => "--:", + TableAlignment::None => "---", }) .unwrap(); } @@ -647,7 +647,7 @@ fn is_autolink<'a>(node: &'a AstNode<'a>, nl: &NodeLink) -> bool { }; let mut real_url: &str = &nl.url; - if &&real_url[..7] == &"mailto:" { + if &real_url[..7] == "mailto:" { real_url = &real_url[7..]; } diff --git a/src/lib.rs b/src/lib.rs index cd7a3053..37bdbff9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,7 +60,20 @@ //! # } //! ``` -#![warn(missing_docs)] +#![deny(missing_docs, + missing_debug_implementations, + missing_copy_implementations, + trivial_casts, + trivial_numeric_casts, + unsafe_code, + unstable_features, + unused_import_braces, + unused_qualifications)] + +#![cfg_attr(feature = "dev", allow(unstable_features))] +#![cfg_attr(feature = "dev", feature(plugin))] +#![cfg_attr(feature = "dev", plugin(clippy))] +#![allow(doc_markdown, cyclomatic_complexity)] extern crate unicode_categories; extern crate typed_arena; diff --git a/src/main.rs b/src/main.rs index 85c92ec6..749bb139 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,20 @@ +//! The `comrak` binary. + +#![deny(missing_docs, + missing_debug_implementations, + missing_copy_implementations, + trivial_casts, + trivial_numeric_casts, + unsafe_code, + unstable_features, + unused_import_braces, + unused_qualifications)] + +#![cfg_attr(feature = "dev", allow(unstable_features))] +#![cfg_attr(feature = "dev", feature(plugin))] +#![cfg_attr(feature = "dev", plugin(clippy))] +#![allow(doc_markdown, cyclomatic_complexity)] + #[macro_use] extern crate clap; extern crate unicode_categories; diff --git a/src/nodes.rs b/src/nodes.rs index aa7acebe..176253dd 100644 --- a/src/nodes.rs +++ b/src/nodes.rs @@ -218,7 +218,7 @@ pub struct NodeCodeBlock { } /// The metadata of a heading. -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug, Clone, Copy)] pub struct NodeHeading { /// The level of the header; from 1 to 6 for ATX headings, 1 or 2 for setext headings. pub level: u32, diff --git a/src/parser/autolink.rs b/src/parser/autolink.rs index 2548f55d..66cc0ff5 100644 --- a/src/parser/autolink.rs +++ b/src/parser/autolink.rs @@ -43,7 +43,7 @@ pub fn process_autolinks<'a>(arena: &'a Arena>, node.insert_after(post); if i + skip < len { let remain = contents[i + skip..].to_string(); - assert!(remain.len() > 0); + assert!(!remain.is_empty()); post.insert_after(make_inline(arena, NodeValue::Text(remain))); } contents.truncate(i); diff --git a/src/parser/inlines.rs b/src/parser/inlines.rs index f0601ae6..cf945e41 100644 --- a/src/parser/inlines.rs +++ b/src/parser/inlines.rs @@ -553,16 +553,14 @@ impl<'a, 'r, 'o> Subject<'a, 'r, 'o> { } pub fn skip_line_end(&mut self) -> bool { - let mut seen_line_end_char = false; + let old_pos = self.pos; if self.peek_char() == Some(&(b'\r')) { self.pos += 1; - seen_line_end_char = true; } if self.peek_char() == Some(&(b'\n')) { self.pos += 1; - seen_line_end_char = true; } - seen_line_end_char || self.eof() + self.pos > old_pos || self.eof() } pub fn handle_entity(&mut self) -> &'a AstNode<'a> { diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 5479c24a..14a1e8f7 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -65,7 +65,7 @@ pub struct Parser<'a, 'o> { options: &'o ComrakOptions, } -#[derive(Default)] +#[derive(Default, Debug, Clone, Copy)] /// Options for both parser and formatter functions. pub struct ComrakOptions { /// [Soft line breaks](http://spec.commonmark.org/0.27/#soft-line-breaks) in the input @@ -355,76 +355,72 @@ impl<'a, 'o> Parser<'a, 'o> { line: &mut String, all_matched: &mut bool) -> Option<&'a AstNode<'a>> { + let (new_all_matched, mut container, should_continue) = self.check_open_blocks_inner(self.root, line); + + *all_matched = new_all_matched; + if !*all_matched { + container = container.parent().unwrap(); + } + + if !should_continue { + None + } else { + Some(container) + } + } + + fn check_open_blocks_inner(&mut self, mut container: &'a AstNode<'a>, line: &mut String) -> (bool, &'a AstNode<'a>, bool) { let mut should_continue = true; - *all_matched = false; - let mut container = self.root; - 'done: loop { - while nodes::last_child_is_open(container) { - container = container.last_child().unwrap(); - let ast = &mut *container.data.borrow_mut(); + while nodes::last_child_is_open(container) { + container = container.last_child().unwrap(); + let ast = &mut *container.data.borrow_mut(); - self.find_first_nonspace(line); + self.find_first_nonspace(line); - match ast.value { - NodeValue::BlockQuote => { - if !self.parse_block_quote_prefix(line) { - break 'done; - } - } - NodeValue::Item(ref nl) => { - if !self.parse_node_item_prefix(line, container, nl) { - break 'done; - } - } - NodeValue::CodeBlock(..) => { - if !self.parse_code_block_prefix( - line, container, ast, &mut should_continue) { - break 'done; - } + match ast.value { + NodeValue::BlockQuote => { + if !self.parse_block_quote_prefix(line) { + return (false, container, should_continue); } - NodeValue::Heading(..) => { - break 'done; - } - NodeValue::HtmlBlock(ref nhb) => { - if !self.parse_html_block_prefix(nhb.block_type) { - break 'done; - } + } + NodeValue::Item(ref nl) => { + if !self.parse_node_item_prefix(line, container, nl) { + return (false, container, should_continue); } - NodeValue::Paragraph => { - if self.blank { - break 'done; - } + } + NodeValue::CodeBlock(..) => { + if !self.parse_code_block_prefix( + line, container, ast, &mut should_continue) { + return (false, container, should_continue); } - NodeValue::Table(..) => { - if !table::matches(&line[self.first_nonspace..]) { - break 'done; - } - continue; + } + NodeValue::HtmlBlock(ref nhb) => { + if !self.parse_html_block_prefix(nhb.block_type) { + return (false, container, should_continue); } - NodeValue::TableRow(..) => { - break 'done; + } + NodeValue::Paragraph => { + if self.blank { + return (false, container, should_continue); } - NodeValue::TableCell => { - break 'done; + } + NodeValue::Table(..) => { + if !table::matches(&line[self.first_nonspace..]) { + return (false, container, should_continue); } - _ => {} + continue; + } + NodeValue::Heading(..) | + NodeValue::TableRow(..) | + NodeValue::TableCell => { + return (false, container, should_continue); } + _ => {} } - - *all_matched = true; - break 'done; - } - - if !*all_matched { - container = container.parent().unwrap(); } - if !should_continue { - None - } else { - Some(container) - } + (true, container, should_continue) } fn open_new_blocks(&mut self, diff --git a/src/scanners.rs b/src/scanners.rs index 624c09b4..a128d51d 100644 --- a/src/scanners.rs +++ b/src/scanners.rs @@ -89,23 +89,23 @@ lazy_static! { pub fn html_block_start(line: &str) -> Option { lazy_static! { static ref RE1: Regex = Regex::new(r"\A(?:<(script|pre|style)([ \t\v\f\r\n]|>))").unwrap(); - static ref RE2: Regex = Regex::new(r"\A(?: