From 4e9b8a224c89d6f99470619553d3ed6a46a44ae1 Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Tue, 14 Jan 2025 11:11:41 +0800 Subject: [PATCH 1/5] feat: enhance evaluator func type_pack_and_check err msg Signed-off-by: he1pa <18012015693@163.com> --- kclvm/evaluator/src/ty.rs | 53 ++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/kclvm/evaluator/src/ty.rs b/kclvm/evaluator/src/ty.rs index 6b7b694d3..82821777a 100644 --- a/kclvm/evaluator/src/ty.rs +++ b/kclvm/evaluator/src/ty.rs @@ -1,7 +1,7 @@ use kclvm_runtime::{ - check_type, dereference_type, is_dict_type, is_list_type, is_type_union, schema_config_meta, - schema_runtime_type, separate_kv, split_type_union, val_plan, ConfigEntryOperationKind, - ValueRef, BUILTIN_TYPES, KCL_TYPE_ANY, PKG_PATH_PREFIX, + check_type, dereference_type, is_dict_type, is_list_type, is_schema_type, is_type_union, + schema_config_meta, schema_runtime_type, separate_kv, split_type_union, val_plan, + ConfigEntryOperationKind, ValueRef, BUILTIN_TYPES, KCL_TYPE_ANY, PKG_PATH_PREFIX, }; use scopeguard::defer; @@ -72,7 +72,7 @@ pub fn type_pack_and_check( let mut checked = false; let mut converted_value = value.clone(); let expected_type = &expected_types.join(" | ").replace('@', ""); - for tpe in expected_types { + for tpe in &expected_types { if !is_schema { converted_value = convert_collection_value(s, value, tpe); } @@ -88,9 +88,50 @@ pub fn type_pack_and_check( } } if !checked { + let mut error_msgs = vec![]; + for tpe in &expected_types { + if is_schema_type(tpe) { + let schema_type_name = if tpe.contains('.') { + if tpe.starts_with(PKG_PATH_PREFIX) { + tpe.to_string() + } else { + format!("{PKG_PATH_PREFIX}{tpe}") + } + } else { + format!("{}.{}", s.current_pkgpath(), tpe) + }; + + if let Some(index) = s.schemas.borrow().get(&schema_type_name) { + let frame = { + let frames = s.frames.borrow(); + frames + .get(*index) + .expect(kcl_error::INTERNAL_ERROR_MSG) + .clone() + }; + if let Proxy::Schema(caller) = &frame.proxy { + if value.is_config() { + let config = value.as_dict_ref(); + for (key, _) in &config.values { + let no_such_attr = + !SchemaEvalContext::has_attr(s, &caller.ctx, key) + && !key.starts_with('_'); + let has_index_signature = + SchemaEvalContext::has_index_signature(s, &caller.ctx); + if !has_index_signature && no_such_attr { + error_msgs + .push(format!("Schema {} not contains attr {}", tpe, key)); + } + } + } + } + } + } + } panic!( - "expect {expected_type}, got {}", - val_plan::type_of(value, true) + "expect {expected_type}, got {}. For details: {}", + val_plan::type_of(value, true), + error_msgs.join(" ") ); } converted_value From ba7b6a6e0ad702d488f6c23ce5d41cd4fa954353 Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Tue, 14 Jan 2025 11:33:31 +0800 Subject: [PATCH 2/5] insert missing attr msg Signed-off-by: he1pa <18012015693@163.com> --- kclvm/evaluator/src/schema.rs | 23 +++++++++++++++++++++++ kclvm/evaluator/src/ty.rs | 11 +++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/kclvm/evaluator/src/schema.rs b/kclvm/evaluator/src/schema.rs index 93d832e75..444b4d0ba 100644 --- a/kclvm/evaluator/src/schema.rs +++ b/kclvm/evaluator/src/schema.rs @@ -205,6 +205,29 @@ impl SchemaEvalContext { false } + /// Get all attribute from schema + pub fn get_attrs(s: &Evaluator, ctx: &SchemaEvalContextRef) -> Vec { + let mut attrs = vec![]; + for stmt in &ctx.borrow().node.body { + if let ast::Stmt::SchemaAttr(attr) = &stmt.node { + attrs.push(attr.name.node.clone()); + } + } + if let Some(index) = ctx.borrow().parent { + let frame = { + let frames = s.frames.borrow(); + frames + .get(index) + .expect(kcl_error::INTERNAL_ERROR_MSG) + .clone() + }; + if let Proxy::Schema(schema) = &frame.proxy { + attrs.extend(SchemaEvalContext::get_attrs(s, &schema.ctx)); + } + } + attrs + } + /// Whether the index signature is the schema context. pub fn has_index_signature(s: &Evaluator, ctx: &SchemaEvalContextRef) -> bool { if ctx.borrow().node.index_signature.is_some() { diff --git a/kclvm/evaluator/src/ty.rs b/kclvm/evaluator/src/ty.rs index 82821777a..f9fc8cb32 100644 --- a/kclvm/evaluator/src/ty.rs +++ b/kclvm/evaluator/src/ty.rs @@ -123,15 +123,22 @@ pub fn type_pack_and_check( .push(format!("Schema {} not contains attr {}", tpe, key)); } } + + for attr in SchemaEvalContext::get_attrs(s, &caller.ctx) { + if !config.values.contains_key(&attr) { + error_msgs + .push(format!("Schema {}'s attr {} is missing", tpe, attr)); + } + } } } } } } panic!( - "expect {expected_type}, got {}. For details: {}", + "expect {expected_type}, got {}. For details:\n{}", val_plan::type_of(value, true), - error_msgs.join(" ") + error_msgs.join("\n") ); } converted_value From b011652fe4ca582fbc92200ddd8fc3896fdd7d38 Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Tue, 14 Jan 2025 11:45:08 +0800 Subject: [PATCH 3/5] fix optional attr Signed-off-by: he1pa <18012015693@163.com> --- kclvm/evaluator/src/schema.rs | 4 ++-- kclvm/evaluator/src/ty.rs | 17 +++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/kclvm/evaluator/src/schema.rs b/kclvm/evaluator/src/schema.rs index 444b4d0ba..a67d4f368 100644 --- a/kclvm/evaluator/src/schema.rs +++ b/kclvm/evaluator/src/schema.rs @@ -206,11 +206,11 @@ impl SchemaEvalContext { } /// Get all attribute from schema - pub fn get_attrs(s: &Evaluator, ctx: &SchemaEvalContextRef) -> Vec { + pub fn get_attrs(s: &Evaluator, ctx: &SchemaEvalContextRef) -> Vec<(String, bool)> { let mut attrs = vec![]; for stmt in &ctx.borrow().node.body { if let ast::Stmt::SchemaAttr(attr) = &stmt.node { - attrs.push(attr.name.node.clone()); + attrs.push((attr.name.node.clone(), attr.is_optional)); } } if let Some(index) = ctx.borrow().parent { diff --git a/kclvm/evaluator/src/ty.rs b/kclvm/evaluator/src/ty.rs index f9fc8cb32..4f4504e6b 100644 --- a/kclvm/evaluator/src/ty.rs +++ b/kclvm/evaluator/src/ty.rs @@ -120,14 +120,15 @@ pub fn type_pack_and_check( SchemaEvalContext::has_index_signature(s, &caller.ctx); if !has_index_signature && no_such_attr { error_msgs - .push(format!("Schema {} not contains attr {}", tpe, key)); + .push(format!("Schema {} does not contain attribute {}", tpe, key)); } } - for attr in SchemaEvalContext::get_attrs(s, &caller.ctx) { - if !config.values.contains_key(&attr) { + for (attr, is_optional) in SchemaEvalContext::get_attrs(s, &caller.ctx) + { + if !config.values.contains_key(&attr) && !is_optional { error_msgs - .push(format!("Schema {}'s attr {} is missing", tpe, attr)); + .push(format!("Schema {}'s attribute {} is missing", tpe, attr)); } } } @@ -136,9 +137,13 @@ pub fn type_pack_and_check( } } panic!( - "expect {expected_type}, got {}. For details:\n{}", + "expect {expected_type}, got {}.{}", val_plan::type_of(value, true), - error_msgs.join("\n") + if error_msgs.is_empty() { + "".to_string() + } else { + format!("For details:\n{}", error_msgs.join("\n")) + } ); } converted_value From 247295ffbdccb79480b8eef5db7994ecb58776b4 Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Tue, 14 Jan 2025 16:05:52 +0800 Subject: [PATCH 4/5] fix ut Signed-off-by: he1pa <18012015693@163.com> --- kclvm/evaluator/src/ty.rs | 16 ++++++++++------ .../runtime_ty/runtime_ty_err_0/stderr.golden | 4 +++- .../types/type_as/type_as_err_2/stderr.golden | 4 +++- .../types/type_as/type_as_err_3/stderr.golden | 4 +++- .../types/type_as/type_as_err_4/stderr.golden | 4 +++- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/kclvm/evaluator/src/ty.rs b/kclvm/evaluator/src/ty.rs index 4f4504e6b..e66063f9b 100644 --- a/kclvm/evaluator/src/ty.rs +++ b/kclvm/evaluator/src/ty.rs @@ -119,16 +119,20 @@ pub fn type_pack_and_check( let has_index_signature = SchemaEvalContext::has_index_signature(s, &caller.ctx); if !has_index_signature && no_such_attr { - error_msgs - .push(format!("Schema {} does not contain attribute {}", tpe, key)); + error_msgs.push(format!( + "Schema {} does not contain attribute {}", + tpe, key + )); } } for (attr, is_optional) in SchemaEvalContext::get_attrs(s, &caller.ctx) { if !config.values.contains_key(&attr) && !is_optional { - error_msgs - .push(format!("Schema {}'s attribute {} is missing", tpe, attr)); + error_msgs.push(format!( + "Schema {}'s attribute {} is missing", + tpe, attr + )); } } } @@ -137,12 +141,12 @@ pub fn type_pack_and_check( } } panic!( - "expect {expected_type}, got {}.{}", + "expect {expected_type}, got {}{}", val_plan::type_of(value, true), if error_msgs.is_empty() { "".to_string() } else { - format!("For details:\n{}", error_msgs.join("\n")) + format!(". For details:\n{}", error_msgs.join("\n")) } ); } diff --git a/test/grammar/types/runtime_ty/runtime_ty_err_0/stderr.golden b/test/grammar/types/runtime_ty/runtime_ty_err_0/stderr.golden index 95f352159..3d1ce11fa 100644 --- a/test/grammar/types/runtime_ty/runtime_ty_err_0/stderr.golden +++ b/test/grammar/types/runtime_ty/runtime_ty_err_0/stderr.golden @@ -2,5 +2,7 @@ error[E3M38]: EvaluationError --> ${CWD}/main.k:7:1 | 7 | person: Person = json.decode('{"err_name": "Alice", "age": 18}') - | expect Person, got dict + | expect Person, got dict.For details: +Schema Person does not contain attribute err_name +Schema Person's attribute name is missing | \ No newline at end of file diff --git a/test/grammar/types/type_as/type_as_err_2/stderr.golden b/test/grammar/types/type_as/type_as_err_2/stderr.golden index 9d5e5183e..dda8d20c1 100644 --- a/test/grammar/types/type_as/type_as_err_2/stderr.golden +++ b/test/grammar/types/type_as/type_as_err_2/stderr.golden @@ -2,5 +2,7 @@ error[E3M38]: EvaluationError --> ${CWD}/main.k:8:1 | 8 | bar = foo as Bar - | expect Bar, got Foo + | expect Bar, got Foo.For details: +Schema Bar does not contain attribute foo +Schema Bar's attribute bar is missing | diff --git a/test/grammar/types/type_as/type_as_err_3/stderr.golden b/test/grammar/types/type_as/type_as_err_3/stderr.golden index 8dc529e3c..dd2933cd8 100644 --- a/test/grammar/types/type_as/type_as_err_3/stderr.golden +++ b/test/grammar/types/type_as/type_as_err_3/stderr.golden @@ -2,5 +2,7 @@ error[E3M38]: EvaluationError --> ${CWD}/child/child.k:15:1 | 15 | base_a: A = _base_a as A - | expect A, got base.A + | expect A, got base.A.For details: +Schema A does not contain attribute bar +Schema A's attribute foo is missing | diff --git a/test/grammar/types/type_as/type_as_err_4/stderr.golden b/test/grammar/types/type_as/type_as_err_4/stderr.golden index 857ba7d21..d363e7192 100644 --- a/test/grammar/types/type_as/type_as_err_4/stderr.golden +++ b/test/grammar/types/type_as/type_as_err_4/stderr.golden @@ -2,5 +2,7 @@ error[E3M38]: EvaluationError --> ${CWD}/main.k:18:1 | 18 | child_a = _child_a as A - | expect A, got child.A + | expect A, got child.A. For details: +Schema A does not contain attribute foo +Schema A's attribute main is missing | From c96632a652ae243672ca1507423fd727405f6cb0 Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Tue, 14 Jan 2025 16:40:50 +0800 Subject: [PATCH 5/5] fix ut Signed-off-by: he1pa <18012015693@163.com> --- test/grammar/types/runtime_ty/runtime_ty_err_0/stderr.golden | 2 +- test/grammar/types/type_as/type_as_err_2/stderr.golden | 2 +- test/grammar/types/type_as/type_as_err_3/stderr.golden | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/grammar/types/runtime_ty/runtime_ty_err_0/stderr.golden b/test/grammar/types/runtime_ty/runtime_ty_err_0/stderr.golden index 3d1ce11fa..aa232308f 100644 --- a/test/grammar/types/runtime_ty/runtime_ty_err_0/stderr.golden +++ b/test/grammar/types/runtime_ty/runtime_ty_err_0/stderr.golden @@ -2,7 +2,7 @@ error[E3M38]: EvaluationError --> ${CWD}/main.k:7:1 | 7 | person: Person = json.decode('{"err_name": "Alice", "age": 18}') - | expect Person, got dict.For details: + | expect Person, got dict. For details: Schema Person does not contain attribute err_name Schema Person's attribute name is missing | \ No newline at end of file diff --git a/test/grammar/types/type_as/type_as_err_2/stderr.golden b/test/grammar/types/type_as/type_as_err_2/stderr.golden index dda8d20c1..35e4fac94 100644 --- a/test/grammar/types/type_as/type_as_err_2/stderr.golden +++ b/test/grammar/types/type_as/type_as_err_2/stderr.golden @@ -2,7 +2,7 @@ error[E3M38]: EvaluationError --> ${CWD}/main.k:8:1 | 8 | bar = foo as Bar - | expect Bar, got Foo.For details: + | expect Bar, got Foo. For details: Schema Bar does not contain attribute foo Schema Bar's attribute bar is missing | diff --git a/test/grammar/types/type_as/type_as_err_3/stderr.golden b/test/grammar/types/type_as/type_as_err_3/stderr.golden index dd2933cd8..d67a20374 100644 --- a/test/grammar/types/type_as/type_as_err_3/stderr.golden +++ b/test/grammar/types/type_as/type_as_err_3/stderr.golden @@ -2,7 +2,7 @@ error[E3M38]: EvaluationError --> ${CWD}/child/child.k:15:1 | 15 | base_a: A = _base_a as A - | expect A, got base.A.For details: + | expect A, got base.A. For details: Schema A does not contain attribute bar Schema A's attribute foo is missing |