From 55785916fdd2f0f019f6d86db384c50d6084a570 Mon Sep 17 00:00:00 2001 From: zongz <68977949+zong-zhe@users.noreply.github.com> Date: Wed, 8 May 2024 18:22:46 +0800 Subject: [PATCH] feat: supports import local file in kcl-vet (#1290) * feat: supports import local file in kcl-vet Signed-off-by: zongz * fix: fix bug Signed-off-by: zongz * fix: make fmt Signed-off-by: zongz * fix: fix test case Signed-off-by: zongz --------- Signed-off-by: zongz --- .../invalid_vet_cases_json/dep/kcl.mod | 5 ++ .../invalid_vet_cases_json/dep/main.k | 2 + .../invalid_vet_cases_json/with_import.k | 4 ++ .../invalid_vet_cases_json/with_import.k.json | 3 + .../invalid_vet_cases_yaml/dep/kcl.mod | 5 ++ .../invalid_vet_cases_yaml/dep/main.k | 2 + .../invalid_vet_cases_yaml/with_import.k | 4 ++ .../with_import.k.stderr.json | 1 + .../invalid_vet_cases_yaml/with_import.k.yaml | 1 + .../vet/test_datas/validate_cases/dep/kcl.mod | 5 ++ .../vet/test_datas/validate_cases/dep/main.k | 2 + .../test_datas/validate_cases/with_import.k | 4 ++ .../validate_cases/with_import.k.json | 5 ++ .../validate_cases/with_import.k.yaml | 2 + kclvm/tools/src/vet/tests.rs | 33 +++++---- kclvm/tools/src/vet/validator.rs | 67 +++++++++++++++---- 16 files changed, 118 insertions(+), 27 deletions(-) create mode 100644 kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/dep/kcl.mod create mode 100644 kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/dep/main.k create mode 100644 kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/with_import.k create mode 100644 kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/with_import.k.json create mode 100644 kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/dep/kcl.mod create mode 100644 kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/dep/main.k create mode 100644 kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k create mode 100644 kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k.stderr.json create mode 100644 kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k.yaml create mode 100644 kclvm/tools/src/vet/test_datas/validate_cases/dep/kcl.mod create mode 100644 kclvm/tools/src/vet/test_datas/validate_cases/dep/main.k create mode 100644 kclvm/tools/src/vet/test_datas/validate_cases/with_import.k create mode 100644 kclvm/tools/src/vet/test_datas/validate_cases/with_import.k.json create mode 100644 kclvm/tools/src/vet/test_datas/validate_cases/with_import.k.yaml diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/dep/kcl.mod b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/dep/kcl.mod new file mode 100644 index 000000000..ad4478c32 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/dep/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "dep" +edition = "v0.8.0" +version = "0.0.1" + diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/dep/main.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/dep/main.k new file mode 100644 index 000000000..eae94c15d --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/dep/main.k @@ -0,0 +1,2 @@ +schema A : + name: str \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/with_import.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/with_import.k new file mode 100644 index 000000000..5d779160f --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/with_import.k @@ -0,0 +1,4 @@ +import .dep as dep + +schema B: + a: dep.A \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/with_import.k.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/with_import.k.json new file mode 100644 index 000000000..6789fb1d7 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/with_import.k.json @@ -0,0 +1,3 @@ +{ + "a": 1 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/dep/kcl.mod b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/dep/kcl.mod new file mode 100644 index 000000000..ad4478c32 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/dep/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "dep" +edition = "v0.8.0" +version = "0.0.1" + diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/dep/main.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/dep/main.k new file mode 100644 index 000000000..eae94c15d --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/dep/main.k @@ -0,0 +1,2 @@ +schema A : + name: str \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k new file mode 100644 index 000000000..5d779160f --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k @@ -0,0 +1,4 @@ +import .dep as dep + +schema B: + a: dep.A \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k.stderr.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k.stderr.json new file mode 100644 index 000000000..a016ac454 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k.stderr.json @@ -0,0 +1 @@ +a: 1 \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k.yaml b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k.yaml new file mode 100644 index 000000000..a016ac454 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/with_import.k.yaml @@ -0,0 +1 @@ +a: 1 \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/validate_cases/dep/kcl.mod b/kclvm/tools/src/vet/test_datas/validate_cases/dep/kcl.mod new file mode 100644 index 000000000..ad4478c32 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/validate_cases/dep/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "dep" +edition = "v0.8.0" +version = "0.0.1" + diff --git a/kclvm/tools/src/vet/test_datas/validate_cases/dep/main.k b/kclvm/tools/src/vet/test_datas/validate_cases/dep/main.k new file mode 100644 index 000000000..eae94c15d --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/validate_cases/dep/main.k @@ -0,0 +1,2 @@ +schema A : + name: str \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/validate_cases/with_import.k b/kclvm/tools/src/vet/test_datas/validate_cases/with_import.k new file mode 100644 index 000000000..5d779160f --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/validate_cases/with_import.k @@ -0,0 +1,4 @@ +import .dep as dep + +schema B: + a: dep.A \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/validate_cases/with_import.k.json b/kclvm/tools/src/vet/test_datas/validate_cases/with_import.k.json new file mode 100644 index 000000000..58198466c --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/validate_cases/with_import.k.json @@ -0,0 +1,5 @@ +{ + "a": { + "name": "name" + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/validate_cases/with_import.k.yaml b/kclvm/tools/src/vet/test_datas/validate_cases/with_import.k.yaml new file mode 100644 index 000000000..7eabf3069 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/validate_cases/with_import.k.yaml @@ -0,0 +1,2 @@ +a: + name: name \ No newline at end of file diff --git a/kclvm/tools/src/vet/tests.rs b/kclvm/tools/src/vet/tests.rs index ca7d3b3b4..8d0f751c8 100644 --- a/kclvm/tools/src/vet/tests.rs +++ b/kclvm/tools/src/vet/tests.rs @@ -315,8 +315,6 @@ mod test_validater { path::{Path, PathBuf}, }; - use regex::Regex; - use crate::{ util::loader::LoaderKind, vet::{ @@ -327,15 +325,24 @@ mod test_validater { use super::{construct_full_path, LOADER_KIND}; - const KCL_TEST_CASES: &[&str] = &["test.k", "simple.k", "list.k", "plain_value.k", "complex.k"]; + const KCL_TEST_CASES: &[&str] = &[ + "test.k", + "simple.k", + "list.k", + "plain_value.k", + "complex.k", + "with_import.k", + ]; + const KCL_TEST_CASES_WITH_CODE: &[&str] = + &["test.k", "simple.k", "list.k", "plain_value.k", "complex.k"]; const VALIDATED_FILE_TYPE: &[&str] = &["json", "yaml"]; #[test] fn test_validator() { test_validate(); println!("test_validate - PASS"); - test_invalid_validate(); - println!("test_invalid_validate - PASS"); + test_invalid_validate_only_code(); + println!("test_invalid_validate_only_code - PASS"); test_validate_with_invalid_kcl_path(); println!("test_validate_with_invalid_kcl_path - PASS"); test_validate_with_invalid_file_path(); @@ -374,7 +381,7 @@ mod test_validater { match validate(opt) { Ok(res) => assert!(res), - Err(_) => panic!("Unreachable"), + Err(err) => assert!(false, "{:?}", err), } } } @@ -490,9 +497,10 @@ mod test_validater { } } - fn test_invalid_validate() { + #[test] + fn test_invalid_validate_only_code() { for (i, file_suffix) in VALIDATED_FILE_TYPE.iter().enumerate() { - for case in KCL_TEST_CASES { + for case in KCL_TEST_CASES_WITH_CODE { let validated_file_path = construct_full_path(&format!( "{}.{}", Path::new("invalid_validate_cases").join(case).display(), @@ -541,11 +549,10 @@ mod test_validater { panic!("unreachable") } Err(err) => { - assert!(Regex::new( - r"^Failed to load KCL file 'validationTempKCLCode.k'. Because .*" - ) - .unwrap() - .is_match(&err.to_string())) + assert_eq!( + err.to_string(), + "Cannot find the kcl file, please check the file path validationTempKCLCode.k" + ); } } } diff --git a/kclvm/tools/src/vet/validator.rs b/kclvm/tools/src/vet/validator.rs index b7dced16f..d878340fd 100644 --- a/kclvm/tools/src/vet/validator.rs +++ b/kclvm/tools/src/vet/validator.rs @@ -68,10 +68,11 @@ use super::expr_builder::ExprBuilder; pub use crate::util::loader::LoaderKind; use anyhow::Result; use kclvm_ast::{ - ast::{AssignStmt, Expr, ExprContext, Identifier, Module, Node, NodeRef, SchemaStmt, Stmt}, + ast::{AssignStmt, Expr, ExprContext, Identifier, Node, NodeRef, Program, SchemaStmt, Stmt}, node_ref, }; -use kclvm_runner::{execute_module, MapErrorResult}; +use kclvm_parser::{LoadProgramOptions, ParseSessionRef}; +use kclvm_runner::{execute, ExecProgramArgs, MapErrorResult}; const TMP_FILE: &str = "validationTempKCLCode.k"; @@ -172,14 +173,27 @@ const TMP_FILE: &str = "validationTempKCLCode.k"; /// } /// ``` pub fn validate(val_opt: ValidateOption) -> Result { - let k_path = match val_opt.kcl_path { - Some(path) => path, - None => TMP_FILE.to_string(), - }; + let k_path = val_opt.kcl_path.unwrap_or_else(|| TMP_FILE.to_string()); + let k_code = val_opt.kcl_code.map_or_else(Vec::new, |code| vec![code]); - let mut module = kclvm_parser::parse_file_force_errors(&k_path, val_opt.kcl_code)?; + let sess = ParseSessionRef::default(); + let mut compile_res = kclvm_parser::load_program( + sess, + vec![k_path] + .iter() + .map(|s| s.as_str()) + .collect::>() + .as_slice(), + Some(LoadProgramOptions { + k_code_list: k_code, + package_maps: Default::default(), + load_plugins: true, + ..Default::default() + }), + None, + )?; - let schemas = filter_schema_stmt(&module); + let schemas = filter_schema_stmt_from_prog(&compile_res.program); let schema_name = match val_opt.schema_name { Some(name) => Some(name), None => schemas.get(0).map(|schema| schema.name.node.clone()), @@ -192,9 +206,26 @@ pub fn validate(val_opt: ValidateOption) -> Result { let assign_stmt = build_assign(&val_opt.attribute_name, validated_expr); - module.body.insert(0, assign_stmt); + match compile_res.program.pkgs.get_mut(kclvm_ast::MAIN_PKG) { + Some(pkg) => { + if let Some(module) = pkg.first_mut() { + module.body.insert(0, assign_stmt); + } else { + return Err(anyhow::anyhow!("No main module found")); + } + } + None => { + return Err(anyhow::anyhow!("No main package found")); + } + } - execute_module(module).map_err_to_result().map(|_| true) + execute( + ParseSessionRef::default(), + compile_res.program, + &ExecProgramArgs::default(), + ) + .map_err_to_result() + .map(|_| true) } fn build_assign(attr_name: &str, node: NodeRef) -> NodeRef { @@ -209,13 +240,21 @@ fn build_assign(attr_name: &str, node: NodeRef) -> NodeRef { })) } -fn filter_schema_stmt(module: &Module) -> Vec<&SchemaStmt> { +fn filter_schema_stmt_from_prog(prog: &Program) -> Vec<&SchemaStmt> { let mut result = vec![]; - for stmt in &module.body { - if let Stmt::Schema(s) = &stmt.node { - result.push(s); + for (pkg_name, modules) in &prog.pkgs { + if pkg_name != kclvm_ast::MAIN_PKG { + continue; + } + for module in modules { + for stmt in &module.body { + if let Stmt::Schema(s) = &stmt.node { + result.push(s); + } + } } } + result }