// 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;
-pub use config::ReportTactic;
-const TO_DO_CHARS: &'static [char] = &['T', 'O', 'D', 'O'];
-const FIX_ME_CHARS: &'static [char] = &['F', 'I', 'X', 'M', 'E'];
+use config::ReportTactic;
+
+const TO_DO_CHARS: &[char] = &['t', 'o', 'd', 'o'];
+const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e'];
// Enabled implementation detail is here because it is
// irrelevant outside the issues module
-impl ReportTactic {
- fn is_enabled(&self) -> bool {
- match *self {
- ReportTactic::Always => true,
- ReportTactic::Unnumbered => true,
- ReportTactic::Never => false,
- }
- }
+fn is_enabled(report_tactic: ReportTactic) -> bool {
+ report_tactic != ReportTactic::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)]
todo_idx: 0,
fixme_idx: 0,
},
- report_todo: report_todo,
- report_fixme: report_fixme,
+ 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 } => {
}
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
+ 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 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,
+ };
+ }
+ 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,
- };
+ 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,
+ 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 == ')' {
NumberPart::CloseParen => {}
}
- self.state = Seeking::Number {
- part: part,
- issue: issue,
- };
+ self.state = Seeking::Number { part, issue };
IssueClassification::None
}
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);
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]
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 {
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()
+ );
}