Skip to content

Commit

Permalink
feat: api list_variables supports get variables from multi-files (#1389)
Browse files Browse the repository at this point in the history
* feat: api list_variables supports get variables from multi-files

Signed-off-by: zongz <[email protected]>

* fix: fix CR comments

Signed-off-by: zongz <[email protected]>

* fix: fix test cases

Signed-off-by: zongz <[email protected]>

---------

Signed-off-by: zongz <[email protected]>
  • Loading branch information
zong-zhe authored Jun 3, 2024
1 parent c07925f commit d0c1eae
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 28 deletions.
6 changes: 3 additions & 3 deletions kclvm/api/src/service/service_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,18 +351,18 @@ impl KclvmServiceImpl {
///
/// let serv = KclvmServiceImpl::default();
/// let args = &ListVariablesArgs {
/// file: Path::new(".").join("src").join("testdata").join("variables").join("main.k").canonicalize().unwrap().display().to_string(),
/// files: vec![Path::new(".").join("src").join("testdata").join("variables").join("main.k").canonicalize().unwrap().display().to_string()],
/// specs: vec!["a".to_string()]
/// };
/// let result = serv.list_variables(args).unwrap();
/// assert_eq!(result.variables.len(), 1);
/// assert_eq!(result.variables.get("a").unwrap().value, "1");
/// ```
pub fn list_variables(&self, args: &ListVariablesArgs) -> anyhow::Result<ListVariablesResult> {
let k_file = args.file.to_string();
let k_files = args.files.clone();
let specs = args.specs.clone();

let select_res = list_variables(k_file, specs)?;
let select_res = list_variables(k_files, specs)?;

let variables: HashMap<String, Variable> = select_res
.variables
Expand Down
2 changes: 1 addition & 1 deletion kclvm/api/src/testdata/list-variables.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"file": "./src/testdata/variables/main.k",
"files": ["./src/testdata/variables/main.k"],
"specs": ["a", "b", "c"]
}
Empty file.
38 changes: 21 additions & 17 deletions kclvm/query/src/selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ use super::util::{invalid_symbol_selector_spec_error, split_field_path};
use anyhow::Result;
use kclvm_ast::ast;
use kclvm_error::diagnostic::Errors;
use kclvm_parser::ParseSession;
use serde::{Deserialize, Serialize};

use std::collections::{HashMap, VecDeque};
use std::{
collections::{HashMap, VecDeque},
sync::Arc,
};

use kclvm_ast::path::get_key_path;

use kclvm_ast::walker::MutSelfWalker;
use kclvm_ast_pretty::{print_ast_node, ASTNode};
use kclvm_parser::parse_file;
use kclvm_parser::load_program;

use kclvm_sema::resolver::Options;

use kclvm_ast::MAIN_PKG;
use kclvm_sema::pre_process::pre_process_program;
use maplit::hashmap;
use kclvm_sema::resolver::Options;
#[derive(Debug, Default)]
/// UnsupportedSelectee is used to store the unsupported selectee, such as if, for, etc.
pub struct UnsupportedSelectee {
Expand Down Expand Up @@ -461,26 +462,29 @@ impl Variable {

/// 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<String>) -> Result<ListVariablesResult> {
pub fn list_variables(files: Vec<String>, specs: Vec<String>) -> Result<ListVariablesResult> {
let mut selector = Selector::new(specs)?;
let parse_result = parse_file(&file, None)?;
let mut load_result = load_program(
Arc::new(ParseSession::default()),
&files.iter().map(AsRef::as_ref).collect::<Vec<&str>>(),
None,
None,
)?;

let mut opts = Options::default();
opts.merge_program = true;
pre_process_program(
&mut ast::Program {
root: file,
pkgs: hashmap! { MAIN_PKG.to_string() => vec![parse_result.module.clone()] },
},
&opts,
);
pre_process_program(&mut load_result.program, &opts);

selector.walk_module(&parse_result.module);
for (_, modules) in load_result.program.pkgs.iter() {
for module in modules.iter() {
selector.walk_module(&module);
}
}

Ok(ListVariablesResult {
variables: selector.select_result,
unsupported: selector.unsupported,
parse_errors: parse_result.errors,
parse_errors: load_result.errors,
})
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
name = "test_list_merged_variables"
edition = "v0.9.0"
version = "0.0.1"

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

import test

_tests = test.Test {
pots: [
test.Pot {
name: "http"
number: 90
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

import test

_tests = test.Test {
aType: "Internet"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
schema Pot:
name: str
number: int

schema Test:
aType?: str
pots?: [Pot]
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

import test

tests = test.Test {
pots: [
test.Pot {
name: "http"
number: 90
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

import test

tests : test.Test {
aType: "Internet"
}
67 changes: 61 additions & 6 deletions kclvm/query/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ fn test_list_variables() {

for (spec, expected, expected_name, op_sym) in test_cases {
let specs = vec![spec.to_string()];
let result = list_variables(file.clone(), specs).unwrap();
let result = list_variables(vec![file.clone()], specs).unwrap();
assert_eq!(result.variables.get(spec).unwrap().value, expected);
assert_eq!(result.variables.get(spec).unwrap().type_name, expected_name);
assert_eq!(result.variables.get(spec).unwrap().op_sym, op_sym);
Expand Down Expand Up @@ -470,7 +470,7 @@ fn test_list_all_variables() {
];

for (spec, expected, expected_name, op_sym) in test_cases {
let result = list_variables(file.clone(), vec![]).unwrap();
let result = list_variables(vec![file.clone()], vec![]).unwrap();
assert_eq!(result.variables.get(spec).unwrap().value, expected);
assert_eq!(result.variables.get(spec).unwrap().type_name, expected_name);
assert_eq!(result.variables.get(spec).unwrap().op_sym, op_sym);
Expand Down Expand Up @@ -521,7 +521,7 @@ fn test_list_unsupported_variables() {

for (spec, expected_code) in test_cases {
let specs = vec![spec.to_string()];
let result = list_variables(file.clone(), specs).unwrap();
let result = list_variables(vec![file.clone()], specs).unwrap();
assert_eq!(result.variables.get(spec), None);
assert_eq!(result.unsupported[0].code, expected_code);
assert_eq!(result.parse_errors.len(), 0);
Expand All @@ -545,7 +545,7 @@ fn test_list_unsupported_variables() {

for (spec, expected_code) in test_cases {
let specs = vec![spec.to_string()];
let result = list_variables(file.clone(), specs).unwrap();
let result = list_variables(vec![file.clone()], specs).unwrap();
assert_eq!(result.variables.get(spec).unwrap().value, expected_code);
}
}
Expand Down Expand Up @@ -626,7 +626,7 @@ fn test_list_variable_with_invalid_kcl() {
.display()
.to_string();
let specs = vec!["a".to_string()];
let result = list_variables(file.clone(), specs).unwrap();
let result = list_variables(vec![file.clone()], specs).unwrap();
assert_eq!(result.variables.get("a"), None);
assert_eq!(result.parse_errors.len(), 2);
assert_eq!(result.parse_errors[0].level, Level::Error);
Expand Down Expand Up @@ -682,7 +682,7 @@ fn test_list_variables_with_file_noexist() {
.display()
.to_string();
let specs = vec!["a".to_string()];
let result = list_variables(file.clone(), specs);
let result = list_variables(vec![file.clone()], specs);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.to_string(), "Cannot find the kcl file, please check the file path ./src/test_data/test_list_variables/noexist.k");
Expand All @@ -702,3 +702,58 @@ fn test_override_file_with_invalid_spec() {
let err = result.err().unwrap();
assert_eq!(err.to_string(), "Invalid spec format '....', expected <field_path>=filed_value>, <field_path>:filed_value>, <field_path>+=filed_value> or <field_path>-");
}

#[test]
fn test_list_merged_variables() {
let file = PathBuf::from("./src/test_data/test_list_variables/test_list_merged_variables")
.canonicalize()
.unwrap();

let test_cases = vec![
(
"override/base.k",
"override/main.k",
vec!["_tests.aType".to_string(), "_tests.pots".to_string()],
r#""Internet""#.to_string(),
r#"[test.Pot {
name: "http"
number: 90
}]"#
.to_string(),
),
(
"union/base.k",
"union/main.k",
vec!["tests.aType".to_string(), "tests.pots".to_string()],
r#""Internet""#.to_string(),
r#"[test.Pot {
name: "http"
number: 90
}]"#
.to_string(),
),
];

for (base_file_name, main_file_name, specs, expected_value1, expected_value2) in test_cases {
let base_file = file.join(base_file_name).display().to_string();
let main_file = file.join(main_file_name).display().to_string();

let result = list_variables(vec![main_file, base_file], specs.clone()).unwrap();
assert_eq!(
result
.variables
.get(&specs.get(0).unwrap().to_string())
.unwrap()
.value,
expected_value1
);
assert_eq!(
result
.variables
.get(&specs.get(1).unwrap().to_string())
.unwrap()
.value,
expected_value2
);
}
}
2 changes: 1 addition & 1 deletion kclvm/spec/gpyrpc/gpyrpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ message OverrideFile_Result {
}

message ListVariables_Args {
string file = 1;
repeated string files = 1;
repeated string specs = 2;
}

Expand Down

0 comments on commit d0c1eae

Please sign in to comment.