Skip to content

Commit de99a74

Browse files
committed
Added LeadingCommentCapture enum tests
1 parent 3e1caaf commit de99a74

File tree

1 file changed

+132
-4
lines changed

1 file changed

+132
-4
lines changed

src/comments.rs

Lines changed: 132 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,16 +344,48 @@ impl Comments {
344344
&self.comments
345345
}
346346

347-
/// Helper method for checking and finding for a comment before a specific
348-
/// line
347+
/// Finds a single comment before a specific line or returns none
349348
///
350349
/// # Parameters
351-
/// - `self` an instance of [`Comments`]
352-
/// - `line` an `u64` value representing the desired line to check above.
350+
/// - [`Comments`] object
351+
/// - An `u64` value representing the desired line to check above.
353352
#[must_use]
354353
pub fn leading_comment(&self, line: u64) -> Option<&Comment> {
355354
self.comments().iter().rev().find(|comment| comment.span().end().line() + 1 == line)
356355
}
356+
357+
/// Finds leading comments before specific line based on [`LeadingCommentCapture`] preference
358+
///
359+
/// # Parameters
360+
/// - [`Comments`] object
361+
/// - An `u64` value representing the desired line to check above.
362+
/// - [`LeadingCommentCapture`] preference
363+
#[must_use]
364+
pub fn leading_comments(&self, line: u64, capture: &LeadingCommentCapture) -> Vec<&Comment> {
365+
let mut comments = Vec::new();
366+
let mut current_line = line;
367+
let mut seen_multiline = false;
368+
while let Some(leading_comment) = self.leading_comment(current_line) {
369+
match capture {
370+
LeadingCommentCapture::SingleNearest => {
371+
comments.push(leading_comment);
372+
break;
373+
}
374+
LeadingCommentCapture::AllLeading => comments.push(leading_comment),
375+
LeadingCommentCapture::AllSingleOneMulti => match leading_comment.kind() {
376+
CommentKind::MultiLine if seen_multiline => break,
377+
CommentKind::MultiLine => {
378+
seen_multiline = true;
379+
comments.push(leading_comment);
380+
}
381+
CommentKind::SingleLine => comments.push(leading_comment),
382+
},
383+
}
384+
current_line = leading_comment.span().start().line();
385+
}
386+
comments.reverse();
387+
comments
388+
}
357389
}
358390

359391
/// Controls how leading comments are captured for a statement.
@@ -781,4 +813,100 @@ CREATE TABLE posts (
781813
assert_eq!(comment.span().end(), comment_vec[i].span().end());
782814
}
783815
}
816+
817+
use crate::comments::LeadingCommentCapture;
818+
819+
fn texts(v: Vec<&Comment>) -> Vec<String> {
820+
v.into_iter().map(|c| c.text().to_owned()).collect()
821+
}
822+
823+
#[test]
824+
fn leading_comment_capture_default_is_single_nearest() {
825+
match LeadingCommentCapture::default() {
826+
LeadingCommentCapture::SingleNearest => {}
827+
_ => panic!("Default for LeadingCommentCapture must be SingleNearest"),
828+
}
829+
}
830+
831+
#[test]
832+
fn leading_comments_single_nearest_and_all_leading_basic_runover()
833+
-> Result<(), Box<dyn std::error::Error>> {
834+
let src = "\
835+
-- c1
836+
-- c2
837+
CREATE TABLE t (id INTEGER);
838+
";
839+
let parsed = Comments::scan_comments(src)?;
840+
let single = parsed.leading_comments(3, &LeadingCommentCapture::SingleNearest);
841+
assert_eq!(texts(single), vec!["c2".to_owned()]);
842+
843+
let all = parsed.leading_comments(3, &LeadingCommentCapture::AllLeading);
844+
assert_eq!(texts(all), vec!["c1".to_owned(), "c2".to_owned()]);
845+
846+
Ok(())
847+
}
848+
849+
#[test]
850+
fn leading_comments_all_leading_stops_at_blank_line() -> Result<(), Box<dyn std::error::Error>>
851+
{
852+
let src = "\
853+
-- c1
854+
855+
-- c2
856+
CREATE TABLE t (id INTEGER);
857+
";
858+
let parsed = Comments::scan_comments(src)?;
859+
let all = parsed.leading_comments(4, &LeadingCommentCapture::AllLeading);
860+
assert_eq!(texts(all), vec!["c2".to_owned()]);
861+
862+
Ok(())
863+
}
864+
865+
#[test]
866+
fn leading_comments_all_single_one_multi_collects_singles_and_one_multiline()
867+
-> Result<(), Box<dyn std::error::Error>> {
868+
let src = "\
869+
/* m
870+
m */
871+
-- s1
872+
-- s2
873+
CREATE TABLE t (id INTEGER);
874+
";
875+
let parsed = Comments::scan_comments(src)?;
876+
let got = parsed.leading_comments(5, &LeadingCommentCapture::AllSingleOneMulti);
877+
assert_eq!(texts(got), vec!["m\nm".to_owned(), "s1".to_owned(), "s2".to_owned(),]);
878+
879+
Ok(())
880+
}
881+
882+
#[test]
883+
fn leading_comments_all_single_one_multi_stops_before_second_multiline()
884+
-> Result<(), Box<dyn std::error::Error>> {
885+
let src = "\
886+
/* m1 */
887+
/* m2 */
888+
-- s1
889+
CREATE TABLE t (id INTEGER);
890+
";
891+
let parsed = Comments::scan_comments(src)?;
892+
let got = parsed.leading_comments(4, &LeadingCommentCapture::AllSingleOneMulti);
893+
assert_eq!(texts(got), vec!["m2".to_owned(), "s1".to_owned()]);
894+
895+
Ok(())
896+
}
897+
898+
#[test]
899+
fn leading_comments_single_nearest_can_return_multiline()
900+
-> Result<(), Box<dyn std::error::Error>> {
901+
let src = "\
902+
/* hello
903+
world */
904+
CREATE TABLE t (id INTEGER);
905+
";
906+
let parsed = Comments::scan_comments(src)?;
907+
let got = parsed.leading_comments(3, &LeadingCommentCapture::SingleNearest);
908+
assert_eq!(texts(got), vec!["hello\nworld".to_owned()]);
909+
910+
Ok(())
911+
}
784912
}

0 commit comments

Comments
 (0)