diff --git a/kclvm/api/src/service/service_impl.rs b/kclvm/api/src/service/service_impl.rs index cd12a6825..f7abf332f 100644 --- a/kclvm/api/src/service/service_impl.rs +++ b/kclvm/api/src/service/service_impl.rs @@ -349,11 +349,12 @@ impl KclvmServiceImpl { let variables: HashMap = select_res .select_result .iter() - .map(|(key, value)| { + .map(|(key, var)| { ( key.clone(), Variable { - value: value.to_string(), + value: var.value.to_string(), + type_name: var.type_name.to_string(), }, ) }) diff --git a/kclvm/query/src/selector.rs b/kclvm/query/src/selector.rs index d6988724e..fa7353d9d 100644 --- a/kclvm/query/src/selector.rs +++ b/kclvm/query/src/selector.rs @@ -25,7 +25,7 @@ pub struct UnsupportedSelectee { /// Selector is used to select the target variable from the kcl program. pub struct Selector { select_specs: Vec, - select_result: HashMap, + select_result: HashMap, unsupported: Vec, inner: SelectorInner, } @@ -147,7 +147,11 @@ impl<'ctx> MutSelfWalker for Selector { let kcode = print_ast_node(ASTNode::Expr(&Box::new(ast::Node::dummy_node( ast::Expr::Schema(unification_stmt.value.node.clone()), )))); - self.select_result.insert(target.to_string(), kcode); + + self.select_result.insert( + target.to_string(), + Variable::new(unification_stmt.value.node.name.node.get_name(), kcode), + ); } else { // if length of spec is largr or equal to target let selector = self.inner.pop_front(); @@ -159,7 +163,10 @@ impl<'ctx> MutSelfWalker for Selector { print_ast_node(ASTNode::Expr(&Box::new(ast::Node::dummy_node( ast::Expr::Schema(unification_stmt.value.node.clone()), )))); - self.select_result.insert(target.to_string(), kcode); + self.select_result.insert( + target.to_string(), + Variable::new(unification_stmt.value.node.name.node.get_name(), kcode), + ); } else { // walk ahead self.walk_schema_expr(&unification_stmt.value.node); @@ -182,6 +189,11 @@ impl<'ctx> MutSelfWalker for Selector { } // get the value source code of the assign statement let kcode = print_ast_node(ASTNode::Expr(&assign_stmt.value)); + let type_name = if let ast::Expr::Schema(schema) = &assign_stmt.value.node { + schema.name.node.get_name() + } else { + "".to_string() + }; // The length of name for variable in top level is 1 if assign_stmt.targets.len() == 1 { let target = &assign_stmt.targets[0]; @@ -189,7 +201,8 @@ impl<'ctx> MutSelfWalker for Selector { target.node.clone(), )))); let key = get_key_path(&target); - self.select_result.insert(key.to_string(), kcode); + self.select_result + .insert(key.to_string(), Variable::new(type_name, kcode)); } } else { // Compare the target with the spec @@ -211,7 +224,14 @@ impl<'ctx> MutSelfWalker for Selector { // matched let kcode = print_ast_node(ASTNode::Expr(&assign_stmt.value)); - self.select_result.insert(target.to_string(), kcode); + let type_name = + if let ast::Expr::Schema(schema) = &assign_stmt.value.node { + schema.name.node.get_name() + } else { + "".to_string() + }; + self.select_result + .insert(target.to_string(), Variable::new(type_name, kcode)); } else { // walk ahead self.walk_expr(&assign_stmt.value.node) @@ -249,8 +269,15 @@ impl<'ctx> MutSelfWalker for Selector { return; } let kcode = print_ast_node(ASTNode::Expr(&item.node.value)); - self.select_result - .insert(self.inner.current_spec.to_string(), kcode); + let type_name = if let ast::Expr::Schema(schema) = &item.node.value.node { + schema.name.node.get_name() + } else { + "".to_string() + }; + self.select_result.insert( + self.inner.current_spec.to_string(), + Variable::new(type_name, kcode), + ); } else { // the spec is still not used up // walk ahead @@ -333,10 +360,22 @@ impl<'ctx> MutSelfWalker for Selector { } pub struct ListVariablesResult { - pub select_result: HashMap, + pub select_result: HashMap, pub unsupported: Vec, } +#[derive(Debug, PartialEq)] +pub struct Variable { + pub type_name: String, + pub value: String, +} + +impl Variable { + pub fn new(type_name: String, value: String) -> Self { + Self { type_name, value } + } +} + /// list_options provides users with the ability to parse kcl program and get all option /// calling information. pub fn list_variables(file: String, specs: Vec) -> Result { diff --git a/kclvm/query/src/test_data/test_list_variables/supported.k b/kclvm/query/src/test_data/test_list_variables/supported.k index 9b1275df5..ec1a749df 100644 --- a/kclvm/query/src/test_data/test_list_variables/supported.k +++ b/kclvm/query/src/test_data/test_list_variables/supported.k @@ -76,4 +76,8 @@ schema Job: job = Job { name = "{}-{}".format("app", "test").lower() +} + +select = a.b.c { + a: 1 } \ No newline at end of file diff --git a/kclvm/query/src/tests.rs b/kclvm/query/src/tests.rs index 872df7da8..7118b1d29 100644 --- a/kclvm/query/src/tests.rs +++ b/kclvm/query/src/tests.rs @@ -225,16 +225,16 @@ fn test_list_variables() { .display() .to_string(); let test_cases = vec![ - ("a", "1"), - ("a1", "2"), - ("a3", "3m"), - ("b1", "True"), - ("b2", "False"), - ("s1", "\"Hello\""), - ("array1", "[1, 2, 3]"), - ("dict1", "{\"a\": 1, \"b\": 2}"), - ("dict1.a", "1"), - ("dict1.b", "2"), + ("a", "1", ""), + ("a1", "2", ""), + ("a3", "3m", ""), + ("b1", "True", ""), + ("b2", "False", ""), + ("s1", "\"Hello\"", ""), + ("array1", "[1, 2, 3]", ""), + ("dict1", "{\"a\": 1, \"b\": 2}", ""), + ("dict1.a", "1", ""), + ("dict1.b", "2", ""), ( "dict2", r#"{ @@ -244,17 +244,19 @@ fn test_list_variables() { "d": 3 } }"#, + "", ), - ("dict2.a", "1"), + ("dict2.a", "1", ""), ( "dict2.b", r#"{ "c": 2 "d": 3 }"#, + "", ), - ("dict2.b.c", "2"), - ("dict2.b.d", "3"), + ("dict2.b.c", "2", ""), + ("dict2.b.d", "3", ""), ( "sha", r#"A { @@ -266,9 +268,10 @@ fn test_list_variables() { } } }"#, + "A", ), - ("sha.name", "\"Hello\""), - ("sha.ids", "[1, 2, 3]"), + ("sha.name", "\"Hello\"", ""), + ("sha.ids", "[1, 2, 3]", ""), ( "sha.data", r#"{ @@ -276,15 +279,17 @@ fn test_list_variables() { "b": {"c": 2} } }"#, + "", ), ( "sha.data.a", r#"{ "b": {"c": 2} }"#, + "", ), - ("sha.data.a.b", r#"{"c": 2}"#), - ("sha.data.a.b.c", "2"), + ("sha.data.a.b", r#"{"c": 2}"#, ""), + ("sha.data.a.b.c", "2", ""), ( "shb", r#"B { @@ -298,6 +303,7 @@ fn test_list_variables() { } } }"#, + "B", ), ( "shb.a", @@ -310,9 +316,10 @@ fn test_list_variables() { } } }"#, + "", ), - ("shb.a.name", "\"HelloB\""), - ("shb.a.ids", "[4, 5, 6]"), + ("shb.a.name", "\"HelloB\"", ""), + ("shb.a.ids", "[4, 5, 6]", ""), ( "shb.a.data", r#"{ @@ -320,23 +327,29 @@ fn test_list_variables() { "e": {"f": 3} } }"#, + "", ), ( "shb.a.data.d", r#"{ "e": {"f": 3} }"#, + "", ), - ("shb.a.data.d.e", "{\"f\": 3}"), - ("uconfa.name", "\"b\""), - ("c.a", "{ids: [7, 8, 9]}"), - ("job.name", r#""{}-{}".format("app", "test").lower()"#), + ("shb.a.data.d.e", "{\"f\": 3}", ""), + ("uconfa.name", "\"b\"", ""), + ("c.a", "{ids: [7, 8, 9]}", ""), + ("job.name", r#""{}-{}".format("app", "test").lower()"#, ""), ]; - for (spec, expected) in test_cases { + for (spec, expected, expected_name) in test_cases { let specs = vec![spec.to_string()]; let result = list_variables(file.clone(), specs).unwrap(); - assert_eq!(result.select_result.get(spec).unwrap(), expected); + assert_eq!(result.select_result.get(spec).unwrap().value, expected); + assert_eq!( + result.select_result.get(spec).unwrap().type_name, + expected_name + ); } } @@ -348,14 +361,14 @@ fn test_list_all_variables() { .display() .to_string(); let test_cases = vec![ - ("a", "1"), - ("a1", "2"), - ("a3", "3m"), - ("b1", "True"), - ("b2", "False"), - ("s1", "\"Hello\""), - ("array1", "[1, 2, 3]"), - ("dict1", "{\"a\": 1, \"b\": 2}"), + ("a", "1", ""), + ("a1", "2", ""), + ("a3", "3m", ""), + ("b1", "True", ""), + ("b2", "False", ""), + ("s1", "\"Hello\"", ""), + ("array1", "[1, 2, 3]", ""), + ("dict1", "{\"a\": 1, \"b\": 2}", ""), ( "dict2", r#"{ @@ -365,6 +378,7 @@ fn test_list_all_variables() { "d": 3 } }"#, + "", ), ( "sha", @@ -377,6 +391,7 @@ fn test_list_all_variables() { } } }"#, + "A", ), ( "shb", @@ -391,16 +406,23 @@ fn test_list_all_variables() { } } }"#, + "B", ), ( "job", r#"Job {name = "{}-{}".format("app", "test").lower()}"#, + "Job", ), + ("select", r#"a.b.c {a: 1}"#, "a.b.c"), ]; - for (spec, expected) in test_cases { + for (spec, expected, expected_name) in test_cases { let result = list_variables(file.clone(), vec![]).unwrap(); - assert_eq!(result.select_result.get(spec).unwrap(), expected); + assert_eq!(result.select_result.get(spec).unwrap().value, expected); + assert_eq!( + result.select_result.get(spec).unwrap().type_name, + expected_name + ); } } diff --git a/kclvm/spec/gpyrpc/gpyrpc.proto b/kclvm/spec/gpyrpc/gpyrpc.proto index e7c026a91..34e4a6217 100644 --- a/kclvm/spec/gpyrpc/gpyrpc.proto +++ b/kclvm/spec/gpyrpc/gpyrpc.proto @@ -303,6 +303,7 @@ message ListVariables_Result { message Variable { string value = 1; + string type_name = 2; } message GetFullSchemaType_Args {