Fixed spread expansion with control characters #109

This commit is contained in:
sagie gur ari 2020-06-06 12:41:38 +00:00
parent 1d8fabb55d
commit 5ff4c4b1e2
4 changed files with 122 additions and 26 deletions

View file

@ -108,7 +108,7 @@ pub(crate) fn expand_by_wrapper(
ExpandedValue::Single(value_string.to_string())
} else {
let chars = value_string.to_string().chars().collect();
match parser::parse_arguments(meta_info, &chars, 0) {
match parser::reparse_arguments(meta_info, &chars, 0) {
Ok(values_option) => match values_option {
Some(values) => ExpandedValue::Multi(values),
None => ExpandedValue::None,

View file

@ -7,6 +7,13 @@ fn get_single_value(output: ExpandedValue) -> String {
}
}
fn get_multi_value(output: ExpandedValue) -> Vec<String> {
match output {
ExpandedValue::Multi(value) => value,
_ => panic!("Invalid type."),
}
}
#[test]
fn expand_by_wrapper_control_chars() {
let mut variables = HashMap::new();
@ -220,3 +227,51 @@ value4:test4
value
);
}
#[test]
fn expand_by_wrapper_control_chars_multi() {
let mut variables = HashMap::new();
variables.insert("FOUND".to_string(), r#"abc/123\\123"#.to_string());
let output = expand_by_wrapper("%{FOUND}", &InstructionMetaInfo::new(), &mut variables);
let value = get_multi_value(output);
assert_eq!(value.len(), 1);
assert_eq!(r#"abc/123\\123"#, value[0]);
}
#[test]
fn expand_by_wrapper_split_multi() {
let mut variables = HashMap::new();
variables.insert("FOUND".to_string(), r#"abc 123"#.to_string());
let output = expand_by_wrapper("%{FOUND}", &InstructionMetaInfo::new(), &mut variables);
let value = get_multi_value(output);
assert_eq!(value.len(), 2);
assert_eq!("abc", value[0]);
assert_eq!("123", value[1]);
}
#[test]
fn expand_by_wrapper_split_complex_multi() {
let mut variables = HashMap::new();
variables.insert(
"FOUND".to_string(),
r#"abc 123 "in quotes" 2
lines"#
.to_string(),
);
let output = expand_by_wrapper("%{FOUND}", &InstructionMetaInfo::new(), &mut variables);
let value = get_multi_value(output);
assert_eq!(value.len(), 4);
assert_eq!("abc", value[0]);
assert_eq!("123", value[1]);
assert_eq!("in quotes", value[2]);
assert_eq!("2\nlines", value[3]);
}

View file

@ -195,12 +195,29 @@ pub(crate) fn parse_arguments(
meta_info: &InstructionMetaInfo,
line_text: &Vec<char>,
start_index: usize,
) -> Result<Option<Vec<String>>, ScriptError> {
parse_arguments_with_options(meta_info, line_text, start_index, false)
}
pub(crate) fn reparse_arguments(
meta_info: &InstructionMetaInfo,
line_text: &Vec<char>,
start_index: usize,
) -> Result<Option<Vec<String>>, ScriptError> {
parse_arguments_with_options(meta_info, line_text, start_index, true)
}
fn parse_arguments_with_options(
meta_info: &InstructionMetaInfo,
line_text: &Vec<char>,
start_index: usize,
control_as_char: bool,
) -> Result<Option<Vec<String>>, ScriptError> {
let mut arguments = vec![];
let mut index = start_index;
loop {
match parse_next_argument(&meta_info, &line_text, index) {
match parse_next_argument(&meta_info, &line_text, index, control_as_char) {
Ok(output) => {
let (next_index, argument) = output;
@ -226,8 +243,17 @@ fn parse_next_argument(
meta_info: &InstructionMetaInfo,
line_text: &Vec<char>,
start_index: usize,
control_as_char: bool,
) -> Result<(usize, Option<String>), ScriptError> {
parse_next_value(&meta_info, &line_text, start_index, true, true, false)
parse_next_value(
&meta_info,
&line_text,
start_index,
true,
!control_as_char,
false,
control_as_char,
)
}
fn parse_next_value(
@ -237,6 +263,7 @@ fn parse_next_value(
allow_quotes: bool,
allow_control: bool,
stop_on_equals: bool,
control_as_char: bool,
) -> Result<(usize, Option<String>), ScriptError> {
let end_index = line_text.len();
@ -286,7 +313,9 @@ fn parse_next_value(
});
}
} else if character == '\\' {
if allow_control {
if control_as_char {
argument.push(character);
} else if allow_control {
in_control = true;
found_variable_prefix = false;
} else {
@ -327,7 +356,9 @@ fn parse_next_value(
});
}
} else if character == '\\' {
if allow_control {
if control_as_char {
argument.push(character);
} else if allow_control {
in_control = true;
} else {
return Err(ScriptError {
@ -379,7 +410,7 @@ fn find_label(
index = index + 1;
if character == LABEL_PREFIX {
match parse_next_value(&meta_info, &line_text, index, false, false, false) {
match parse_next_value(&meta_info, &line_text, index, false, false, false, false) {
Ok(output) => {
let (next_index, value) = output;
index = next_index;
@ -421,7 +452,15 @@ fn find_output_and_command(
start_index: usize,
instruction: &mut ScriptInstruction,
) -> Result<usize, ScriptError> {
match parse_next_value(&meta_info, &line_text, start_index, false, false, true) {
match parse_next_value(
&meta_info,
&line_text,
start_index,
false,
false,
true,
false,
) {
Ok(output) => {
let (next_index, value) = output;
@ -444,7 +483,9 @@ fn find_output_and_command(
}
if instruction.output.is_some() {
match parse_next_value(&meta_info, &line_text, index, false, false, false) {
match parse_next_value(
&meta_info, &line_text, index, false, false, false, false,
) {
Ok(output) => {
let (next_index, value) = output;

View file

@ -56,7 +56,7 @@ fn parse_pre_process_line_just_command_with_arguments() {
#[test]
fn parse_next_argument_empty() {
let chars = "".chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -69,7 +69,7 @@ fn parse_next_argument_empty() {
#[test]
fn parse_next_argument_spaces_only() {
let chars = " ".chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -82,7 +82,7 @@ fn parse_next_argument_spaces_only() {
#[test]
fn parse_next_argument_value_only() {
let chars = "test".chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -95,7 +95,7 @@ fn parse_next_argument_value_only() {
#[test]
fn parse_next_argument_value_after_spaces() {
let chars = " test".chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -108,7 +108,7 @@ fn parse_next_argument_value_after_spaces() {
#[test]
fn parse_next_argument_value_in_middle_of_spaces() {
let chars = " test ".chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -121,7 +121,7 @@ fn parse_next_argument_value_in_middle_of_spaces() {
#[test]
fn parse_next_argument_value_in_middle_of_spaces_start_in_middle_of_value() {
let chars = " test ".chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 3);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 3, false);
assert!(result.is_ok());
@ -134,7 +134,7 @@ fn parse_next_argument_value_in_middle_of_spaces_start_in_middle_of_value() {
#[test]
fn parse_next_argument_value_with_quots() {
let chars = r#" "test" "#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -147,7 +147,7 @@ fn parse_next_argument_value_with_quots() {
#[test]
fn parse_next_argument_empty_with_quots() {
let chars = r#" "" "#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -160,7 +160,7 @@ fn parse_next_argument_empty_with_quots() {
#[test]
fn parse_next_argument_value_with_control() {
let chars = r#" \"test\"\\\n\r\t test "#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -173,7 +173,7 @@ fn parse_next_argument_value_with_control() {
#[test]
fn parse_next_argument_value_with_space_in_middle() {
let chars = r#" "test \"test\"" "#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -186,7 +186,7 @@ fn parse_next_argument_value_with_space_in_middle() {
#[test]
fn parse_next_argument_value_with_comment_in_middle() {
let chars = r#" "test \"test\" #test test" "#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -199,7 +199,7 @@ fn parse_next_argument_value_with_comment_in_middle() {
#[test]
fn parse_next_argument_value_with_comment_afterwards() {
let chars = r#" test#comment"#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -212,7 +212,7 @@ fn parse_next_argument_value_with_comment_afterwards() {
#[test]
fn parse_next_argument_value_with_comment_afterwards_wrapped_with_quotes() {
let chars = r#" "test#comment""#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -225,7 +225,7 @@ fn parse_next_argument_value_with_comment_afterwards_wrapped_with_quotes() {
#[test]
fn parse_next_argument_value_with_control_error() {
let chars = r#" \a "#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_err());
}
@ -233,7 +233,7 @@ fn parse_next_argument_value_with_control_error() {
#[test]
fn parse_next_argument_value_with_partial_variable_control_error() {
let chars = r#" \$ "#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_err());
}
@ -241,7 +241,7 @@ fn parse_next_argument_value_with_partial_variable_control_error() {
#[test]
fn parse_next_argument_value_with_control_end_error() {
let chars = r#" \"#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_err());
}
@ -249,7 +249,7 @@ fn parse_next_argument_value_with_control_end_error() {
#[test]
fn parse_next_argument_value_with_variable_control() {
let chars = r#" \${out} "#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_ok());
@ -262,7 +262,7 @@ fn parse_next_argument_value_with_variable_control() {
#[test]
fn parse_next_argument_value_with_quote_end_error() {
let chars = r#" ""#.chars().collect();
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0);
let result = parse_next_argument(&InstructionMetaInfo::new(), &chars, 0, false);
assert!(result.is_err());
}