]> git.lizzy.rs Git - rust.git/blobdiff - src/issues.rs
rewrite_string: retain blank lines that are trailing
[rust.git] / src / issues.rs
index 0efe0c31c78a1f0dc6c862e273db765bf0ff28b4..ad7babca118109a3278f94880bf0c98afb64b761 100644 (file)
@@ -8,44 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Objects for seeking through a char stream for occurences of TODO and FIXME.
+// Objects for seeking through a char stream for occurrences of TODO and FIXME.
 // Depending on the loaded configuration, may also check that these have an
 // associated issue number.
 
 use std::fmt;
 
-static TO_DO_CHARS: &'static [char] = &['T', 'O', 'D', 'O'];
-static FIX_ME_CHARS: &'static [char] = &['F', 'I', 'X', 'M', 'E'];
+use config::ReportTactic;
 
-#[derive(Clone, Copy)]
-pub enum ReportTactic {
-    Always,
-    Unnumbered,
-    Never
-}
+const TO_DO_CHARS: &[char] = &['t', 'o', 'd', 'o'];
+const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e'];
 
-impl ReportTactic {
-    fn is_enabled(&self) -> bool {
-        match *self {
-            ReportTactic::Always => true,
-            ReportTactic::Unnumbered => true,
-            ReportTactic::Never => false
-        }
-    }
+// Enabled implementation detail is here because it is
+// irrelevant outside the issues module
+fn is_enabled(report_tactic: ReportTactic) -> bool {
+    report_tactic != ReportTactic::Never
 }
 
-impl_enum_decodable!(ReportTactic, Always, Unnumbered, Never);
-
 #[derive(Clone, Copy)]
 enum Seeking {
-    Issue {
-        todo_idx: usize,
-        fixme_idx: usize
-    },
-    Number {
-        issue: Issue,
-        part: NumberPart
-    }
+    Issue { todo_idx: usize, fixme_idx: usize },
+    Number { issue: Issue, part: NumberPart },
 }
 
 #[derive(Clone, Copy)]
@@ -53,7 +36,7 @@ enum NumberPart {
     OpenParen,
     Pound,
     Number,
-    CloseParen
+    CloseParen,
 }
 
 #[derive(PartialEq, Eq, Debug, Clone, Copy)]
@@ -70,7 +53,11 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
             IssueType::Todo => "TODO",
             IssueType::Fixme => "FIXME",
         };
-        let details = if self.missing_number { " without issue number" } else { "" };
+        let details = if self.missing_number {
+            " without issue number"
+        } else {
+            ""
+        };
 
         write!(fmt, "{}{}", msg, details)
     }
@@ -79,13 +66,13 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
 #[derive(PartialEq, Eq, Debug, Clone, Copy)]
 enum IssueType {
     Todo,
-    Fixme
+    Fixme,
 }
 
 enum IssueClassification {
     Good,
     Bad(Issue),
-    None
+    None,
 }
 
 pub struct BadIssueSeeker {
@@ -97,19 +84,29 @@ pub struct BadIssueSeeker {
 impl BadIssueSeeker {
     pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker {
         BadIssueSeeker {
-            state: Seeking::Issue { todo_idx: 0, fixme_idx: 0 },
-            report_todo: report_todo,
-            report_fixme: report_fixme,
+            state: Seeking::Issue {
+                todo_idx: 0,
+                fixme_idx: 0,
+            },
+            report_todo,
+            report_fixme,
         }
     }
 
+    pub fn is_disabled(&self) -> bool {
+        !is_enabled(self.report_todo) && !is_enabled(self.report_fixme)
+    }
+
     // Check whether or not the current char is conclusive evidence for an
     // unnumbered TO-DO or FIX-ME.
     pub fn inspect(&mut self, c: char) -> Option<Issue> {
         match self.state {
-            Seeking::Issue { todo_idx, fixme_idx } => {
+            Seeking::Issue {
+                todo_idx,
+                fixme_idx,
+            } => {
                 self.state = self.inspect_issue(c, todo_idx, fixme_idx);
-            },
+            }
             Seeking::Number { issue, part } => {
                 let result = self.inspect_number(c, issue, part);
 
@@ -117,7 +114,10 @@ pub fn inspect(&mut self, c: char) -> Option<Issue> {
                     return None;
                 }
 
-                self.state = Seeking::Issue { todo_idx: 0, fixme_idx: 0 };
+                self.state = Seeking::Issue {
+                    todo_idx: 0,
+                    fixme_idx: 0,
+                };
 
                 if let IssueClassification::Bad(issue) = result {
                     return Some(issue);
@@ -129,56 +129,60 @@ pub fn inspect(&mut self, c: char) -> Option<Issue> {
     }
 
     fn inspect_issue(&mut self, c: char, mut todo_idx: usize, mut fixme_idx: usize) -> Seeking {
-        // FIXME: Should we also check for lower case characters?
-        if self.report_todo.is_enabled() && c == TO_DO_CHARS[todo_idx] {
-            todo_idx += 1;
-            if todo_idx == TO_DO_CHARS.len() {
-                return Seeking::Number {
-                    issue: Issue {
-                        issue_type: IssueType::Todo,
-                        missing_number: if let ReportTactic::Unnumbered = self.report_todo {
-                            true
-                        } else {
-                            false
-                        }
-                    },
-                    part: NumberPart::OpenParen
-                };
-            }
-            fixme_idx = 0;
-        } else if self.report_fixme.is_enabled() && c == FIX_ME_CHARS[fixme_idx] {
-            // Exploit the fact that the character sets of todo and fixme
-            // are disjoint by adding else.
-            fixme_idx += 1;
-            if fixme_idx == FIX_ME_CHARS.len() {
-                return Seeking::Number {
-                    issue: Issue {
-                        issue_type: IssueType::Fixme,
-                        missing_number: if let ReportTactic::Unnumbered = self.report_fixme {
-                            true
-                        } else {
-                            false
-                        }
-                    },
-                    part: NumberPart::OpenParen
-                };
+        if let Some(lower_case_c) = c.to_lowercase().next() {
+            if is_enabled(self.report_todo) && lower_case_c == TO_DO_CHARS[todo_idx] {
+                todo_idx += 1;
+                if todo_idx == TO_DO_CHARS.len() {
+                    return Seeking::Number {
+                        issue: Issue {
+                            issue_type: IssueType::Todo,
+                            missing_number: if let ReportTactic::Unnumbered = self.report_todo {
+                                true
+                            } else {
+                                false
+                            },
+                        },
+                        part: NumberPart::OpenParen,
+                    };
+                }
+                fixme_idx = 0;
+            } else if is_enabled(self.report_fixme) && lower_case_c == FIX_ME_CHARS[fixme_idx] {
+                // Exploit the fact that the character sets of todo and fixme
+                // are disjoint by adding else.
+                fixme_idx += 1;
+                if fixme_idx == FIX_ME_CHARS.len() {
+                    return Seeking::Number {
+                        issue: Issue {
+                            issue_type: IssueType::Fixme,
+                            missing_number: if let ReportTactic::Unnumbered = self.report_fixme {
+                                true
+                            } else {
+                                false
+                            },
+                        },
+                        part: NumberPart::OpenParen,
+                    };
+                }
+                todo_idx = 0;
+            } else {
+                todo_idx = 0;
+                fixme_idx = 0;
             }
-            todo_idx = 0;
-        } else {
-            todo_idx = 0;
-            fixme_idx = 0;
         }
 
-        Seeking::Issue { todo_idx: todo_idx, fixme_idx: fixme_idx }
+        Seeking::Issue {
+            todo_idx,
+            fixme_idx,
+        }
     }
 
-    fn inspect_number(&mut self,
-                      c: char,
-                      issue: Issue,
-                      mut part: NumberPart)
-        -> IssueClassification
-    {
-        if ! issue.missing_number || c == '\n' {
+    fn inspect_number(
+        &mut self,
+        c: char,
+        issue: Issue,
+        mut part: NumberPart,
+    ) -> IssueClassification {
+        if !issue.missing_number || c == '\n' {
             return IssueClassification::Bad(issue);
         } else if c == ')' {
             return if let NumberPart::CloseParen = part {
@@ -195,26 +199,23 @@ fn inspect_number(&mut self,
                 } else {
                     part = NumberPart::Pound;
                 }
-            },
+            }
             NumberPart::Pound => {
                 if c == '#' {
                     part = NumberPart::Number;
                 }
-            },
+            }
             NumberPart::Number => {
                 if c >= '0' && c <= '9' {
                     part = NumberPart::CloseParen;
                 } else {
                     return IssueClassification::Bad(issue);
                 }
-            },
+            }
             NumberPart::CloseParen => {}
         }
 
-        self.state = Seeking::Number {
-            part: part,
-            issue: issue
-        };
+        self.state = Seeking::Number { part, issue };
 
         IssueClassification::None
     }
@@ -224,12 +225,15 @@ fn inspect_number(&mut self,
 fn find_unnumbered_issue() {
     fn check_fail(text: &str, failing_pos: usize) {
         let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered);
-        assert_eq!(Some(failing_pos), text.chars().position(|c| seeker.inspect(c).is_some()));
+        assert_eq!(
+            Some(failing_pos),
+            text.find(|c| seeker.inspect(c).is_some())
+        );
     }
 
     fn check_pass(text: &str) {
         let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered);
-        assert_eq!(None, text.chars().position(|c| seeker.inspect(c).is_some()));
+        assert_eq!(None, text.find(|c| seeker.inspect(c).is_some()));
     }
 
     check_fail("TODO\n", 4);
@@ -252,21 +256,41 @@ fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTacti
         text.chars().any(|c| seeker.inspect(c).is_some())
     }
 
-    assert!(is_bad_issue("TODO(@maintainer, #1222, hello)\n",
-                         ReportTactic::Always,
-                         ReportTactic::Never));
-
-    assert!(! is_bad_issue("TODO: no number\n",
-                           ReportTactic::Never,
-                           ReportTactic::Always));
-
-    assert!(is_bad_issue("This is a FIXME(#1)\n",
-                         ReportTactic::Never,
-                         ReportTactic::Always));
-
-    assert!(! is_bad_issue("bad FIXME\n",
-                           ReportTactic::Always,
-                           ReportTactic::Never));
+    assert!(is_bad_issue(
+        "TODO(@maintainer, #1222, hello)\n",
+        ReportTactic::Always,
+        ReportTactic::Never,
+    ));
+
+    assert!(!is_bad_issue(
+        "TODO: no number\n",
+        ReportTactic::Never,
+        ReportTactic::Always,
+    ));
+
+    assert!(!is_bad_issue(
+        "Todo: mixed case\n",
+        ReportTactic::Never,
+        ReportTactic::Always,
+    ));
+
+    assert!(is_bad_issue(
+        "This is a FIXME(#1)\n",
+        ReportTactic::Never,
+        ReportTactic::Always,
+    ));
+
+    assert!(is_bad_issue(
+        "This is a FixMe(#1) mixed case\n",
+        ReportTactic::Never,
+        ReportTactic::Always,
+    ));
+
+    assert!(!is_bad_issue(
+        "bad FIXME\n",
+        ReportTactic::Always,
+        ReportTactic::Never,
+    ));
 }
 
 #[test]
@@ -274,24 +298,30 @@ fn issue_type() {
     let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never);
     let expected = Some(Issue {
         issue_type: IssueType::Todo,
-        missing_number: false
+        missing_number: false,
     });
 
-    assert_eq!(expected,
-               "TODO(#100): more awesomeness".chars()
-                                       .map(|c| seeker.inspect(c))
-                                       .find(Option::is_some)
-                                       .unwrap());
+    assert_eq!(
+        expected,
+        "TODO(#100): more awesomeness"
+            .chars()
+            .map(|c| seeker.inspect(c))
+            .find(Option::is_some)
+            .unwrap()
+    );
 
     let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered);
     let expected = Some(Issue {
         issue_type: IssueType::Fixme,
-        missing_number: true
+        missing_number: true,
     });
 
-    assert_eq!(expected,
-               "Test. FIXME: bad, bad, not good".chars()
-                                                .map(|c| seeker.inspect(c))
-                                                .find(Option::is_some)
-                                                .unwrap());
+    assert_eq!(
+        expected,
+        "Test. FIXME: bad, bad, not good"
+            .chars()
+            .map(|c| seeker.inspect(c))
+            .find(Option::is_some)
+            .unwrap()
+    );
 }