on master help sign in
Add test cases for existing pair matching logic. (#6027)

* Add test cases for existing pair matching logic. * fix clippy

commit3849ca4c2abdb1c6076d391eab4c3f43dda30234 authorKyle Smith <askreet@gmail.com> dateTue 7 Mar 2023, 21:10 (4 years ago) parent8dd1ab4
1 file changed+116−29
helix-core/src/surround.rs+116−29
helix-core/src/surround.rs+116−29
@@ -275,51 +275,138 @@ mod test {
275275
276276 #[test]
277277 fn test_get_surround_pos() {
278− let doc = Rope::from("(some) (chars)\n(newline)");
279− let slice = doc.slice(..);
280− let selection = Selection::new(
281− SmallVec::from_slice(&[Range::point(2), Range::point(9), Range::point(20)]),
282− 0,
283− );
278+ #[rustfmt::skip]
279+ let (doc, selection, expectations) =
280+ rope_with_selections_and_expectations(
281+ "(some) (chars)\n(newline)",
282+ "_ ^ _ _ ^ _\n_ ^ _"
283+ );
284284
285− // cursor on s[o]me, c[h]ars, newl[i]ne
286285 assert_eq!(
287− get_surround_pos(slice, &selection, Some('('), 1)
288− .unwrap()
289− .as_slice(),
290− &[0, 5, 7, 13, 15, 23]
286+ get_surround_pos(doc.slice(..), &selection, Some('('), 1).unwrap(),
287+ expectations
291288 );
292289 }
293290
294291 #[test]
295− fn test_get_surround_pos_bail() {
296− let doc = Rope::from("[some]\n(chars)xx\n(newline)");
297− let slice = doc.slice(..);
292+ fn test_get_surround_pos_bail_different_surround_chars() {
293+ #[rustfmt::skip]
294+ let (doc, selection, _) =
295+ rope_with_selections_and_expectations(
296+ "[some]\n(chars)xx\n(newline)",
297+ " ^ \n ^ \n "
298+ );
298299
299− let selection =
300− Selection::new(SmallVec::from_slice(&[Range::point(2), Range::point(9)]), 0);
301− // cursor on s[o]me, c[h]ars
302300 assert_eq!(
303− get_surround_pos(slice, &selection, Some('('), 1),
304− Err(Error::PairNotFound) // different surround chars
301+ get_surround_pos(doc.slice(..), &selection, Some('('), 1),
302+ Err(Error::PairNotFound)
305303 );
304+ }
305+
306+ #[test]
307+ fn test_get_surround_pos_bail_overlapping_surround_chars() {
308+ #[rustfmt::skip]
309+ let (doc, selection, _) =
310+ rope_with_selections_and_expectations(
311+ "[some]\n(chars)xx\n(newline)",
312+ " \n ^ \n ^ "
313+ );
306314
307− let selection = Selection::new(
308− SmallVec::from_slice(&[Range::point(14), Range::point(24)]),
309− 0,
310− );
311− // cursor on [x]x, newli[n]e
312315 assert_eq!(
313− get_surround_pos(slice, &selection, Some('('), 1),
316+ get_surround_pos(doc.slice(..), &selection, Some('('), 1),
314317 Err(Error::PairNotFound) // overlapping surround chars
315318 );
319+ }
320+
321+ #[test]
322+ fn test_get_surround_pos_bail_cursor_overlap() {
323+ #[rustfmt::skip]
324+ let (doc, selection, _) =
325+ rope_with_selections_and_expectations(
326+ "[some]\n(chars)xx\n(newline)",
327+ " ^^ \n \n "
328+ );
316329
317− let selection =
318− Selection::new(SmallVec::from_slice(&[Range::point(2), Range::point(3)]), 0);
319− // cursor on s[o][m]e
320330 assert_eq!(
321− get_surround_pos(slice, &selection, Some('['), 1),
331+ get_surround_pos(doc.slice(..), &selection, Some('['), 1),
322332 Err(Error::CursorOverlap)
323333 );
324334 }
335+
336+ #[test]
337+ fn test_find_nth_pairs_pos_quote_success() {
338+ #[rustfmt::skip]
339+ let (doc, selection, expectations) =
340+ rope_with_selections_and_expectations(
341+ "some 'quoted text' on this 'line'\n'and this one'",
342+ " _ ^ _ \n "
343+ );
344+
345+ assert_eq!(2, expectations.len());
346+ assert_eq!(
347+ find_nth_pairs_pos(doc.slice(..), '\'', selection.primary(), 1)
348+ .expect("find should succeed"),
349+ (expectations[0], expectations[1])
350+ )
351+ }
352+
353+ #[test]
354+ fn test_find_nth_pairs_pos_nested_quote_success() {
355+ #[rustfmt::skip]
356+ let (doc, selection, expectations) =
357+ rope_with_selections_and_expectations(
358+ "some 'nested 'quoted' text' on this 'line'\n'and this one'",
359+ " _ ^ _ \n "
360+ );
361+
362+ assert_eq!(2, expectations.len());
363+ assert_eq!(
364+ find_nth_pairs_pos(doc.slice(..), '\'', selection.primary(), 2)
365+ .expect("find should succeed"),
366+ (expectations[0], expectations[1])
367+ )
368+ }
369+
370+ #[test]
371+ fn test_find_nth_pairs_pos_inside_quote_ambiguous() {
372+ #[rustfmt::skip]
373+ let (doc, selection, _) =
374+ rope_with_selections_and_expectations(
375+ "some 'nested 'quoted' text' on this 'line'\n'and this one'",
376+ " ^ \n "
377+ );
378+
379+ assert_eq!(
380+ find_nth_pairs_pos(doc.slice(..), '\'', selection.primary(), 1),
381+ Err(Error::CursorOnAmbiguousPair)
382+ )
383+ }
384+
385+ // Create a Rope and a matching Selection using a specification language.
386+ // ^ is a single-point selection.
387+ // _ is an expected index. These are returned as a Vec<usize> for use in assertions.
388+ fn rope_with_selections_and_expectations(
389+ text: &str,
390+ spec: &str,
391+ ) -> (Rope, Selection, Vec<usize>) {
392+ if text.len() != spec.len() {
393+ panic!("specification must match text length -- are newlines aligned?");
394+ }
395+
396+ let rope = Rope::from(text);
397+
398+ let selections: SmallVec<[Range; 1]> = spec
399+ .match_indices('^')
400+ .into_iter()
401+ .map(|(i, _)| Range::point(i))
402+ .collect();
403+
404+ let expectations: Vec<usize> = spec
405+ .match_indices('_')
406+ .into_iter()
407+ .map(|(i, _)| i)
408+ .collect();
409+
410+ (rope, Selection::new(selections, 0), expectations)
411+ }
325412}