From 1d8fabb55df1361af3758cc46f2e5d94f68ea0cc Mon Sep 17 00:00:00 2001 From: sagie gur ari Date: Fri, 5 Jun 2020 21:38:28 +0000 Subject: [PATCH] Fixed end command bug which directed execution to wrong sub command when multiple script contexts are running #110 --- CHANGELOG.md | 4 +++ .../src/sdk/std/flowcontrol/end/mod.rs | 14 ++++++-- .../src/sdk/std/on_error/on_error/mod_test.rs | 5 ++- .../sdk/std/on_error/set_error/mod_test.rs | 5 ++- duckscript_sdk/src/types/command.rs | 3 ++ duckscript_sdk/src/types/scope.rs | 34 +++++++++++++++++++ duckscript_sdk/src/utils/state.rs | 11 +++++- duckscript_sdk/src/utils/state_test.rs | 11 +++++- 8 files changed, 81 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b561da7..e6b3c3d 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## CHANGELOG +### v0.4.3 + +* Fixed end command bug which directed execution to wrong sub command when multiple script contexts are running #110 + ### v0.4.2 (2020-06-05) * Fixed parsing issue for commands evaluated by other commands (for example if conditions) diff --git a/duckscript_sdk/src/sdk/std/flowcontrol/end/mod.rs b/duckscript_sdk/src/sdk/std/flowcontrol/end/mod.rs index c0b72f3..53cb410 100755 --- a/duckscript_sdk/src/sdk/std/flowcontrol/end/mod.rs +++ b/duckscript_sdk/src/sdk/std/flowcontrol/end/mod.rs @@ -1,3 +1,4 @@ +use crate::types::scope::get_line_context_name; use crate::utils::state::get_core_sub_state_for_command; use duckscript::runner; use duckscript::types::command::{Command, CommandResult, Commands}; @@ -14,10 +15,18 @@ mod mod_test; static END_STATE_KEY: &str = "end"; pub(crate) static END_COMMAND_NAME: &str = "end"; +fn get_key(line: usize, state: &mut HashMap) -> String { + let mut key = get_line_context_name(state); + key.push_str("::"); + key.push_str(&line.to_string()); + + key +} + fn get_command(line: usize, state: &mut HashMap) -> Option { + let key = get_key(line, state); let sub_state = get_core_sub_state_for_command(state, END_STATE_KEY.to_string()); - let key = line.to_string(); match sub_state.get(&key) { Some(state_value) => match state_value { StateValue::String(command) => Some(command.clone()), @@ -33,9 +42,10 @@ fn get_command(line: usize, state: &mut HashMap) -> Option, command: String) { + let key = get_key(line, state); let sub_state = get_core_sub_state_for_command(state, END_STATE_KEY.to_string()); - sub_state.insert(line.to_string(), StateValue::String(command)); + sub_state.insert(key, StateValue::String(command)); } #[derive(Clone)] diff --git a/duckscript_sdk/src/sdk/std/on_error/on_error/mod_test.rs b/duckscript_sdk/src/sdk/std/on_error/on_error/mod_test.rs index 952da33..50028dc 100644 --- a/duckscript_sdk/src/sdk/std/on_error/on_error/mod_test.rs +++ b/duckscript_sdk/src/sdk/std/on_error/on_error/mod_test.rs @@ -21,7 +21,10 @@ fn run_valid() { CommandValidation::Match("out".to_string(), "false".to_string()), ); - let sub_state_value = context.state.get("duckscriptsdk::on_error").unwrap(); + let sub_state_value = context + .state + .get("duckscriptsdk::command::on_error") + .unwrap(); match sub_state_value { StateValue::SubState(sub_state) => { match sub_state.get("error").unwrap() { diff --git a/duckscript_sdk/src/sdk/std/on_error/set_error/mod_test.rs b/duckscript_sdk/src/sdk/std/on_error/set_error/mod_test.rs index 730dd1c..8a31bbb 100644 --- a/duckscript_sdk/src/sdk/std/on_error/set_error/mod_test.rs +++ b/duckscript_sdk/src/sdk/std/on_error/set_error/mod_test.rs @@ -20,7 +20,10 @@ fn run_valid() { CommandValidation::None, ); - let sub_state_value = context.state.get("duckscriptsdk::on_error").unwrap(); + let sub_state_value = context + .state + .get("duckscriptsdk::command::on_error") + .unwrap(); match sub_state_value { StateValue::SubState(sub_state) => { match sub_state.get("error").unwrap() { diff --git a/duckscript_sdk/src/types/command.rs b/duckscript_sdk/src/types/command.rs index 908ab8e..0718661 100644 --- a/duckscript_sdk/src/types/command.rs +++ b/duckscript_sdk/src/types/command.rs @@ -1,4 +1,5 @@ use crate::types::scope::clear; +use crate::types::scope::set_line_context_name; use crate::utils::state::{get_handles_sub_state, put_handle}; use duckscript::types::command::{Command, CommandResult, Commands, GoToValue}; use duckscript::types::error::ScriptError; @@ -91,6 +92,7 @@ impl Command for AliasCommand { CommandResult::Error("Invalid arguments provided.".to_string()) } else { let start_count = variables.len(); + let line_context_name = set_line_context_name(&self.scope_name, state); // define script arguments let mut handle_option = None; @@ -199,6 +201,7 @@ impl Command for AliasCommand { None => (), } clear(&self.scope_name, variables); + set_line_context_name(&line_context_name, state); let end_count = variables.len(); if start_count < end_count { diff --git a/duckscript_sdk/src/types/scope.rs b/duckscript_sdk/src/types/scope.rs index f3fbd6e..8740c6e 100644 --- a/duckscript_sdk/src/types/scope.rs +++ b/duckscript_sdk/src/types/scope.rs @@ -1,5 +1,39 @@ +use crate::utils::state::get_core_sub_state_for_runtime; +use duckscript::types::runtime::StateValue; use std::collections::HashMap; +static CONTEXT_NAME_SUB_STATE_KEY: &str = "line_context_name"; +static CONTEXT_NAME_STATE_KEY: &str = "name"; + +pub(crate) fn get_line_context_name(state: &mut HashMap) -> String { + let sub_state = get_core_sub_state_for_runtime(state, CONTEXT_NAME_SUB_STATE_KEY.to_string()); + + match sub_state.get(CONTEXT_NAME_STATE_KEY) { + Some(state_value) => match state_value { + StateValue::String(value) => value.clone(), + _ => { + // remove corrupted data + sub_state.remove(CONTEXT_NAME_STATE_KEY); + + "".to_string() + } + }, + None => "".to_string(), + } +} + +pub(crate) fn set_line_context_name(name: &str, state: &mut HashMap) -> String { + let previous_name = get_line_context_name(state); + + let sub_state = get_core_sub_state_for_runtime(state, CONTEXT_NAME_SUB_STATE_KEY.to_string()); + sub_state.insert( + CONTEXT_NAME_STATE_KEY.to_string(), + StateValue::String(name.to_string()), + ); + + previous_name +} + pub(crate) fn clear(name: &str, variables: &mut HashMap) { let mut scope_name = name.to_string(); scope_name.push_str("::"); diff --git a/duckscript_sdk/src/utils/state.rs b/duckscript_sdk/src/utils/state.rs index 89b3ad2..f67d547 100644 --- a/duckscript_sdk/src/utils/state.rs +++ b/duckscript_sdk/src/utils/state.rs @@ -11,11 +11,20 @@ mod state_test; static HANDLE_SUB_STATE_KEY: &str = "handles"; +pub(crate) fn get_core_sub_state_for_runtime( + state: &mut HashMap, + name: String, +) -> &mut HashMap { + let sub_state_name = pckg::concat("duckscriptsdk::runtime", &name); + + get_sub_state(sub_state_name, state) +} + pub(crate) fn get_core_sub_state_for_command( state: &mut HashMap, name: String, ) -> &mut HashMap { - let sub_state_name = pckg::concat("duckscriptsdk", &name); + let sub_state_name = pckg::concat("duckscriptsdk::command", &name); get_sub_state(sub_state_name, state) } diff --git a/duckscript_sdk/src/utils/state_test.rs b/duckscript_sdk/src/utils/state_test.rs index 7f450f1..2e987a0 100644 --- a/duckscript_sdk/src/utils/state_test.rs +++ b/duckscript_sdk/src/utils/state_test.rs @@ -1,12 +1,21 @@ use super::*; +#[test] +fn get_core_sub_state_for_runtime_valid() { + let mut state = HashMap::new(); + let value = get_core_sub_state_for_runtime(&mut state, "test".to_string()); + + assert!(value.is_empty()); + assert!(state.contains_key("duckscriptsdk::runtime::test")); +} + #[test] fn get_core_sub_state_for_command_valid() { let mut state = HashMap::new(); let value = get_core_sub_state_for_command(&mut state, "test".to_string()); assert!(value.is_empty()); - assert!(state.contains_key("duckscriptsdk::test")); + assert!(state.contains_key("duckscriptsdk::command::test")); } #[test]