Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: api list_variables supports get variables from multi-files #1389

Merged
merged 3 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just use &[String] or Vec<String> instead of Vec<&str>


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
Loading