From fbfc6f8d8c43f1dac9761221f285e3b19213de10 Mon Sep 17 00:00:00 2001 From: Fabian Boehm Date: Wed, 10 Jan 2024 17:04:54 +0100 Subject: [PATCH] Fix highlighting for slices with quotes This would highlight `$var["foo"]` as an error because parse_util_slice_length didn't advance the iterator. There's got to be a nicer way to write this. --- fish-rust/src/parse_util.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/fish-rust/src/parse_util.rs b/fish-rust/src/parse_util.rs index 5b4758b8f..1aef2a4e6 100644 --- a/fish-rust/src/parse_util.rs +++ b/fish-rust/src/parse_util.rs @@ -31,7 +31,7 @@ use std::ops; /// Handles slices: the square brackets in an expression like $foo[5..4] -/// \return the length of the slice starting at \p in, or 0 if there is no slice, or -1 on error. +/// \return the length of the slice starting at \p in, or 0 if there is no slice, or None on error. /// This never accepts incomplete slices. pub fn parse_util_slice_length(input: &wstr) -> Option { const openc: char = '['; @@ -46,11 +46,20 @@ pub fn parse_util_slice_length(input: &wstr) -> Option { let mut bracket_count = 1; let mut pos = 0; - for c in chars { + while let Some(c) = chars.next() { pos += 1; if !escaped { if ['\'', '"'].contains(&c) { + let oldpos = pos; pos = quote_end(input, pos, c)?; + // We need to advance the iterator as well + if pos - oldpos > 0 { + // nth(0) advances by 1 + chars.nth(pos - oldpos - 1)?; + } else { + // Quotes aren't over, slice is invalid + return None; + } } else if c == openc { bracket_count += 1; } else if c == closec { @@ -1804,6 +1813,16 @@ fn test_parse_util_cmdsubst_extent() { ); } +#[test] +#[serial] +fn test_parse_util_slice_length() { + test_init(); + assert_eq!(parse_util_slice_length(L!("[2]")), Some(3)); + assert_eq!(parse_util_slice_length(L!("[12]")), Some(4)); + assert_eq!(parse_util_slice_length(L!("[\"foo\"]")), Some(7)); + assert_eq!(parse_util_slice_length(L!("[\"foo\"")), None); +} + #[test] #[serial] fn test_escape_quotes() {