litcheck_filecheck/rules/
empty.rs1use crate::common::*;
2
3#[derive(Debug)]
4pub struct CheckEmpty {
5 span: SourceSpan,
6}
7impl CheckEmpty {
8 pub fn new(span: SourceSpan) -> Self {
9 Self { span }
10 }
11}
12impl Spanned for CheckEmpty {
13 fn span(&self) -> SourceSpan {
14 self.span
15 }
16}
17impl Rule for CheckEmpty {
18 fn kind(&self) -> Check {
19 Check::Empty
20 }
21
22 fn apply<'input, 'context, C>(&self, context: &mut C) -> DiagResult<Matches<'input>>
23 where
24 C: Context<'input, 'context> + ?Sized,
25 {
26 let cursor = context.cursor_mut();
28 let next_line_start = cursor.start_of_next_line();
29 let next_eol = cursor
30 .next_newline_from(next_line_start)
31 .unwrap_or_else(|| cursor.end_of_file());
32 let next_line = next_line_start..next_eol;
33 if cursor.at_end_of_line() && next_line.is_empty() {
34 let span = SourceSpan::from(next_line_start..next_eol);
35 cursor.set_start(next_eol);
37 Ok(MatchResult {
38 ty: MatchType::MatchFoundAndExpected,
39 info: Some(MatchInfo::new(span, self.span)),
40 }
41 .into())
42 } else {
43 Ok(MatchResult {
44 ty: MatchType::Failed(CheckFailedError::MatchNoneButExpected {
45 span: self.span,
46 match_file: context.match_file(),
47 note: None,
48 }),
49 info: None,
50 }
51 .into())
52 }
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn check_empty_test() -> DiagResult<()> {
62 let mut context = TestContext::new();
63 context.with_checks("CHECK-EMPTY:").with_input(
64 "
65abc
66
67
68def",
69 );
70 let mut mctx = context.match_context();
71 let rule = CheckEmpty::new(SourceSpan::from(0..12));
72 let matches = rule
73 .apply(&mut mctx)
74 .expect("expected non-fatal application of rule");
75 let test_result = TestResult::from_matches(matches, &mctx);
76 assert!(test_result.is_failed());
77 match test_result.errors() {
78 [CheckFailedError::MatchNoneButExpected { .. }] => (),
79 _ => return test_result.into_result().map(|_| ()).map_err(Report::new),
80 }
81
82 mctx.cursor_mut().set_start(5);
84
85 let matches = rule
86 .apply(&mut mctx)
87 .expect("expected non-fatal application of rule");
88 let test_result = TestResult::from_matches(matches, &mctx);
89 assert!(test_result.is_ok());
90 assert_eq!(test_result.num_matched(), 1);
91
92 let matched = test_result.into_result()?;
93 assert_eq!(matched[0].span.offset(), 6);
94 let buffer = mctx.cursor().buffer();
95 assert_eq!(buffer[5], b'\n');
96 assert_eq!(buffer[6], b'\n');
97 assert_eq!(buffer[7], b'd');
98 assert_eq!(matched[0].span.len(), 0);
99
100 Ok(())
101 }
102}