This commit is contained in:
HWienhold 2025-08-03 19:57:29 +02:00
parent 373c6c01a5
commit d3e6304cfb
6 changed files with 254 additions and 22 deletions

57
Cargo.lock generated
View File

@ -530,6 +530,12 @@ dependencies = [
"log",
]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.10"
@ -788,13 +794,19 @@ dependencies = [
"ahash",
]
[[package]]
name = "hashbrown"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
[[package]]
name = "hashlink"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
dependencies = [
"hashbrown",
"hashbrown 0.14.5",
]
[[package]]
@ -1021,6 +1033,16 @@ dependencies = [
"icu_properties",
]
[[package]]
name = "indexmap"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
dependencies = [
"equivalent",
"hashbrown 0.15.4",
]
[[package]]
name = "infer"
version = "0.2.3"
@ -1494,6 +1516,17 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
dependencies = [
"js-sys",
"serde",
"wasm-bindgen",
]
[[package]]
name = "serde_derive"
version = "1.0.218"
@ -1540,6 +1573,19 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_yaml"
version = "0.9.34+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [
"indexmap",
"itoa",
"ryu",
"serde",
"unsafe-libyaml",
]
[[package]]
name = "sha1"
version = "0.6.1"
@ -1922,6 +1968,12 @@ dependencies = [
"subtle",
]
[[package]]
name = "unsafe-libyaml"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
[[package]]
name = "url"
version = "2.5.4"
@ -2208,6 +2260,9 @@ dependencies = [
"log",
"once_cell",
"regex",
"serde",
"serde-wasm-bindgen",
"serde_yaml",
"strum",
"strum_macros",
"surf",

View File

@ -235,10 +235,34 @@ impl<'a> YamlWrapper<'a> {
path: YamlPath,
) -> Option<(HashMap<String, PropertyInfo>, HashMap<String, ValueInfo>)> {
log::info!("Generating ext info for path: {:?}", path);
let SingleNodeInfo { keys, values, meta } =
context.generate_single_node_stuff(&self.yaml, Some(schema), path.clone());
let a = context.generate_property_info(&self.yaml, Some(schema), path.clone());
let b = context.genereate_value_info(&self.yaml, Some(schema), path.clone());
Some((a, b))
//Some((a, b));
println!("path: {path:?}");
println!("keys: {:#?}", a);
println!("keys2: {:#?}", keys);
println!("values: {:#?}", b.keys());
println!("values2: {:#?}", values.keys());
assert_eq!(a.len(), keys.len());
assert_eq!(b.len(), values.len());
for k in a.keys().cloned() {
assert!(keys.contains_key(k.as_str()));
assert_eq!(a.get(k.as_str()), keys.get(k.as_str()));
}
for k in b.keys().cloned() {
assert!(values.contains_key(k.as_str()));
assert_eq!(b.get(k.as_str()), values.get(k.as_str()));
}
//assert_eq!(&a, &keys);
//assert_eq!(&b, &values);
return Some((keys, values));
/* let b = context.with_ref_node(Some(schema), path, |node| {
Some(
node.compute_ext_path_info(&self.yaml, context, path),
@ -257,9 +281,8 @@ impl<'a> YamlWrapper<'a> {
log::info!("Generating ext info for path: {:?}", path);
let keys = context.generate_property_info(&self.yaml, Some(schema), path.clone());
let values = context.genereate_value_info(&self.yaml, Some(schema), path.clone());
Some(SingleNodeInfo::with_suggested_values(keys, values))
Some(SingleNodeInfo::with_suggestions(keys, values))
/* let b = context.with_ref_node(Some(schema), path, |node| {
Some(
@ -269,7 +292,7 @@ impl<'a> YamlWrapper<'a> {
});
*/
}
pub fn get_path_for_line_col(&self, line: usize, col: usize) -> Option<YamlPath> {
// yaml_rust2 starts counting w/ line 1
// also need to handle when line / col would point to a commented section

View File

@ -3,6 +3,7 @@ use super::super::{
node::SchemaNode,
utils::keys::ArrayKeywords,
};
use crate::info::types::{ExtInfoGen, PropertyInfo, SnExtInfGen, ValueInfo};
use crate::{
error::{
parse::SchemaParseError,
@ -12,6 +13,7 @@ use crate::{
info::{
generation::{InfoGenerator, PathInfoGenerator},
node::YamlNode,
types::SingleNodeInfo,
validate::{PartialValidResult, Schemavalidator, YamlValidator},
},
schema::{
@ -23,9 +25,6 @@ use crate::{
},
},
};
use crate::{
info::types::{ExtInfoGen, PropertyInfo, ValueInfo},
};
use std::collections::HashMap;
use yaml_rust2::Yaml;
@ -252,6 +251,38 @@ impl<'a, 'b> PathInfoGenerator<'a, 'b> for ArrayScheme<'a> {
}
}
impl<'a: 'b, 'b, 'c: 'b> SnExtInfGen<'b, 'c, SingleNodeInfo> for ArrayScheme<'a> {
fn compute_ext_info2(&self, yaml: &'c Yaml, storage: &'b Context<'b>) -> SingleNodeInfo {
if let Some(info) = self.item_definition.as_ref() {
// passin Null as somewhere above
info.compute_ext_info(&Yaml::Null, storage)
} else {
HashMap::new()
}
.into()
}
// TODO
fn compute_ext_path_info2(
&self,
yaml: &'c Yaml,
storage: &'b Context<'b>,
mut path: YamlPath,
) -> SingleNodeInfo {
match path.shift() {
None => self.compute_ext_info2(yaml, storage),
Some(SchemaPathSegment::Index(i)) => {
let yaml_new = yaml.get_idx_opt_yaml(i).unwrap_or(&Yaml::Null);
self.item_definition
.as_ref()
.map(|x| x.compute_ext_path_info2(yaml_new, storage, path))
.unwrap_or_default()
}
_ => HashMap::new().into(),
}
}
}
impl<'a: 'b, 'b, 'c: 'b> ExtInfoGen<'b, 'c, PropertyInfo> for ArrayScheme<'a> {
fn compute_ext_info(
&self,

View File

@ -40,12 +40,8 @@ pub enum Constrain<'a> {
}
impl<'a: 'b, 'b, 'c: 'b> SnExtInfGen<'b, 'c, SingleNodeInfo> for Constrain<'a> {
fn compute_ext_info2(
&self,
yaml: &'c Yaml,
storage: &'b Context<'b>,
) -> SingleNodeInfo {
let res = match self {
fn compute_ext_info2(&self, yaml: &'c Yaml, storage: &'b Context<'b>) -> SingleNodeInfo {
let res = match self {
Constrain::Array(array_scheme) => array_scheme.compute_ext_info2(yaml, storage),
Constrain::Object(object_scheme) => object_scheme.compute_ext_info2(yaml, storage),
Constrain::Generic(general_contrains) => {
@ -57,7 +53,6 @@ impl<'a: 'b, 'b, 'c: 'b> SnExtInfGen<'b, 'c, SingleNodeInfo> for Constrain<'a> {
res
}
fn compute_ext_path_info2(
&self,
yaml: &'c Yaml,

View File

@ -7,15 +7,13 @@ use super::super::{
node::SchemaNode,
utils::keys::ObjectKeyWords,
};
use crate::info::node::YamlNode;
use crate::info::types::{merge_info, BaseInfo, ExtInfoGen, PropertyInfo, ValueInfo};
use crate::info::validate::{
PartialValidResult, Schemavalidator, YamlValidator,
};
use crate::info::types::{merge_info, BaseInfo, ExtInfoGen, PropertyInfo, SnExtInfGen, ValueInfo};
use crate::info::validate::{PartialValidResult, Schemavalidator, YamlValidator};
use crate::info::{
generation::{InfoGenerator, PathInfoGenerator},
types::NodeBaseInfo,
};
use crate::info::{node::YamlNode, types::SingleNodeInfo};
use crate::schema::utils::helper::PropFromKey;
use crate::schema::utils::path::try_map_opt_child_node;
use crate::schema::utils::path::{
@ -547,6 +545,121 @@ impl<'a, 'b> PathInfoGenerator<'a, 'b> for ObjectScheme<'a> {
}
}
impl<'a: 'b, 'b, 'c: 'b> SnExtInfGen<'b, 'c, SingleNodeInfo> for ObjectScheme<'a> {
fn compute_ext_info2(&self, yaml: &'c Yaml, storage: &'b Context<'b>) -> SingleNodeInfo {
//return self.compute_ext_info(yaml, storage).into();
let mut info = self
.properties
.iter()
.map(|(k, n)| match n.get_bool() {
Some(true) => (k.to_string(), BaseInfo::empty().into()),
Some(false) => (
k.to_string(),
BaseInfo::empty()
.with_used(false)
.with_disallowed(true)
.into(),
),
None => (k.to_string(), n.get_node_info(storage).into()),
})
.collect::<HashMap<_, _>>();
if let Some(v) = self.required.as_ref() {
for key in v {
info.entry(key.to_string())
.or_insert(PropertyInfo::new())
.set_required(true);
}
}
let used_properties = keys_from_yaml(yaml);
for key in used_properties {
let hash_key = key.to_string();
if let Some(v) = info.get_mut(&hash_key) {
v.set_used(true);
} else if self.is_locally_referenced(key) {
let mut prop_info = PropertyInfo::new();
prop_info.set_used(true);
info.insert(hash_key, prop_info);
} else if let Some(additional_prop) = self.additional_properties.as_ref() {
let prop_info = match additional_prop.get_bool() {
Some(true) => BaseInfo::empty().with_used(true).into(),
Some(false) => BaseInfo::empty()
.with_used(false)
.with_disallowed(true)
.into(),
None => {
let mut prop_info: PropertyInfo =
additional_prop.get_node_info(storage).into();
prop_info.set_used(true);
prop_info
}
};
info.insert(hash_key, prop_info);
}
}
SingleNodeInfo::with_keys(info)
}
fn compute_ext_path_info2(
&self,
yaml: &'c Yaml,
storage: &'b Context<'b>,
mut path: YamlPath,
) -> SingleNodeInfo {
match path.shift() {
None => self.compute_ext_info2(yaml, storage),
Some(SchemaPathSegment::Path(pat)) if !self.is_locally_referenced(pat.as_str()) => {
log::debug!(
"Computing ext path info for {:?} - shifted seg: {:?} is referenced",
path,
pat
);
self.additional_properties
.as_ref()
.filter(|_| !self.get_ref_node_properties(storage).contains(&&*pat))
.inspect(|_| log::trace!("additional properties found to apply"))
.and_then(|add_prop| {
yaml.get_str_opt_yaml(&*pat).map(|child_yaml| {
add_prop.compute_ext_path_info2(child_yaml, storage, path)
})
})
.unwrap_or_default()
}
Some(SchemaPathSegment::Path(pat)) => {
log::debug!(
"Computing ext path info for {:?} - shifted seg: {:?} is referenced",
path,
pat
);
let step_down = yaml.get_str_opt_yaml(&pat).unwrap_or(&Yaml::Null);
log::debug!(
"Stepped down... is hash?: {:?}",
step_down.as_hash().is_some()
);
let pp = self.pattern_properties.as_ref().map(|x| {
x.iter()
.filter(key_of_pair_match(pat.as_str())) // filters the pairs with regex
.map(|(_, v)| v.compute_ext_path_info2(step_down, storage, path.clone()))
.sum()
});
let p = self
.properties
.get(pat.as_str())
.map(|x| x.compute_ext_path_info2(step_down, storage, path));
match (p, pp) {
(Some(p), Some(pp)) => p + pp,
(Some(p), None) | (None, Some(p)) => p,
_ => HashMap::new().into(),
}
}
_ => SingleNodeInfo::new(),
}
}
}
impl<'a: 'b, 'b, 'c: 'b> ExtInfoGen<'b, 'c, PropertyInfo> for ObjectScheme<'a> {
fn compute_ext_info(
&self,

View File

@ -7,7 +7,7 @@ use yaml_rust2::Yaml;
use crate::data::cache::get_schema;
use crate::error::{validate::ValidationError, with_context::WError};
use crate::info::node::YamlNode;
use crate::info::types::{ExtInfoGen, PropertyInfo, ValueInfo};
use crate::info::types::{ExtInfoGen, PropertyInfo, SingleNodeInfo, SnExtInfGen, ValueInfo};
use super::node::SchemaNode;
use super::{meta::path::YamlPath, wrapper::Schema};
@ -79,6 +79,21 @@ impl<'a> Context<'a> {
schema.compute_ext_path_info(yaml, self, path)
})
}
pub fn generate_single_node_stuff(
&'a self,
yaml: &'a Yaml,
file: Option<&'a str>,
path: YamlPath,
) -> SingleNodeInfo {
log::info!("Generating ext info for path: {:?}", path);
self.with_schema_file(file, |schema| {
println!(
"Generating ext info for path: {:?}\n{:#?}\n \n{:#?}",
path, schema, yaml
);
schema.compute_ext_path_info2(yaml, self, path)
})
}
pub fn generate_property_info(
&'a self,
yaml: &'a Yaml,