]> git.lizzy.rs Git - rust.git/blobdiff - src/issues.rs
rewrite_string: retain blank lines that are trailing
[rust.git] / src / issues.rs
index 34d5b8ab2c440b7aaabd0791dff06f1d9778991d..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)]
@@ -101,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);
 
@@ -121,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);
@@ -133,54 +129,59 @@ 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 {
+    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 == ')' {
@@ -198,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
     }
@@ -227,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);
@@ -255,40 +256,72 @@ 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]
 fn issue_type() {
     let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never);
-    let expected = Some(Issue { issue_type: IssueType::Todo, missing_number: false });
-
-    assert_eq!(expected,
-               "TODO(#100): more awesomeness".chars()
-                                       .map(|c| seeker.inspect(c))
-                                       .find(Option::is_some)
-                                       .unwrap());
+    let expected = Some(Issue {
+        issue_type: IssueType::Todo,
+        missing_number: false,
+    });
+
+    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 });
-
-    assert_eq!(expected,
-               "Test. FIXME: bad, bad, not good".chars()
-                                                .map(|c| seeker.inspect(c))
-                                                .find(Option::is_some)
-                                                .unwrap());
+    let expected = Some(Issue {
+        issue_type: IssueType::Fixme,
+        missing_number: true,
+    });
+
+    assert_eq!(
+        expected,
+        "Test. FIXME: bad, bad, not good"
+            .chars()
+            .map(|c| seeker.inspect(c))
+            .find(Option::is_some)
+            .unwrap()
+    );
 }