1
1
mirror of https://github.com/tweag/nickel.git synced 2024-10-04 23:27:15 +03:00

Fix panic when pprint ast with empty strings

This commit is contained in:
Yann Hamdaoui 2022-06-30 16:16:11 +02:00
parent 34b3b8ca8b
commit 65f1292349
No known key found for this signature in database
GPG Key ID: DEF1D3D3A7E8BCCA

View File

@ -5,23 +5,29 @@ pub use pretty::{DocAllocator, DocBuilder, Pretty};
use regex::Regex;
use std::collections::HashMap;
/// helper to find the min number of `%` sign needed to interpolate
/// a string containing this chunk.
/// Helper to find the min number of `%` sign needed to interpolate a string containing this chunk.
fn min_interpolate_sign(text: &str) -> usize {
let reg = Regex::new(r#"([%]+\{)|("[%]+m)"#).unwrap();
reg.find_iter(text).fold(0, |nb, m| {
reg.find_iter(text)
.map(|m| {
let d = m.end() - m.start();
// if the match end with `{` the nb of `%` is equal to the size of the match.
// This because a `%*{` match len is nb of `%` + 1. It's corect because we are
// looking for the minimum number of `%` to perform interpolation on this string
// Finaly, if the match ends with `m` we return match len - 1 because of the
// extra `"`. In this case, we could improve, because interpolation actualy
// need no more than a different number of `%` than the `"%*m` sequence.
// But this way is valid anyway and easyer to describe algorithmicaly.
// We iterate over all sequences `%+{` and `"%+m`, which could clash with the interpolation
// syntax, and return the maximum number of `%` insead each sequence.
//
// For the case of a closing delimiter `"%m`, we could actually be slightly smarter as we
// don't necessarily need more `%`, but just a different number of `%`. For example, if the
// string contains only one `"%%m`, then single `%` delimiters like `m%"` and `"%m` would
// be fine. But picking the maximum
//
// TODO: Improve the `"%*m` case if necessary.
let d = if m.as_str().ends_with("{") { d } else { d - 1 };
nb.max(d)
if m.as_str().ends_with("{") {
d
} else {
d - 1
}
})
.max()
.unwrap_or(1)
}
fn sorted_map<'a, K: Ord, V>(m: &'a HashMap<K, V>) -> Vec<(&'a K, &'a V)> {
@ -238,7 +244,7 @@ where
}, // be sure we have at least 1 `%` sign when an interpolation is present
)
.max()
.unwrap();
.unwrap_or(1);
let interp: String = std::iter::repeat("%").take(nb_perc).collect();
allocator
.intersperse(