Merge pull request 'feature/return-highlight-error' (#22) from feature/return-highlight-error into main
Reviewed-on: #22
This commit is contained in:
commit
9e53289731
@ -3,6 +3,9 @@
|
||||
use strum_macros::Display;
|
||||
use thiserror::Error;
|
||||
#[derive(Error, Debug, Display)]
|
||||
// TODO: NonYamlError is prob wrong - i may wanna collect here eyerything that i dont know where to put otherwise
|
||||
pub enum NonYamlError {
|
||||
Io(#[from] std::io::Error),
|
||||
ScanError(#[from] yaml_rust2::ScanError),
|
||||
NoYamlFound,
|
||||
}
|
||||
|
||||
67
src/code/highlight.rs
Normal file
67
src/code/highlight.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use serde::Serialize;
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
|
||||
use crate::error::validate::ValidationError;
|
||||
#[wasm_bindgen]
|
||||
#[derive(Serialize, Clone, Copy)]
|
||||
pub enum HighlightErrorSeverity {
|
||||
Error = 1,
|
||||
Warning = 2,
|
||||
Information = 3,
|
||||
Hint = 4,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct HighlightError {
|
||||
message: String,
|
||||
start: usize,
|
||||
end: usize,
|
||||
severity: HighlightErrorSeverity,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl HighlightError {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(
|
||||
message: String,
|
||||
start: usize,
|
||||
end: usize,
|
||||
severity: HighlightErrorSeverity,
|
||||
) -> HighlightError {
|
||||
HighlightError {
|
||||
message,
|
||||
start,
|
||||
end,
|
||||
severity,
|
||||
}
|
||||
}
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn message(&self) -> String {
|
||||
self.message.clone()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn start(&self) -> usize {
|
||||
self.start
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn end(&self) -> usize {
|
||||
self.end
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn severity(&self) -> HighlightErrorSeverity {
|
||||
self.severity
|
||||
}
|
||||
}
|
||||
impl From<(usize, usize, ValidationError)> for HighlightError {
|
||||
fn from((start, end, error): (usize, usize, ValidationError)) -> Self {
|
||||
Self {
|
||||
message: error.to_string(),
|
||||
start,
|
||||
end,
|
||||
severity: HighlightErrorSeverity::Error,
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/code/mod.rs
Normal file
1
src/code/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod highlight;
|
||||
@ -1,6 +1,8 @@
|
||||
use log::info;
|
||||
use yaml_rust2::Yaml;
|
||||
|
||||
use crate::{
|
||||
add_err::NonYamlError,
|
||||
error::{validate::ValidationError, with_context::WError},
|
||||
parser::{
|
||||
facade::{ParLoader, YamlLoad},
|
||||
@ -20,32 +22,37 @@ pub struct YamlWrapper<'a> {
|
||||
yaml: Yaml,
|
||||
location_map: Mark,
|
||||
validation_result: Vec<WError<ValidationError>>,
|
||||
marker_map: Vec<(usize, usize, ValidationError)>,
|
||||
_marker_map: Vec<(usize, usize, ValidationError)>,
|
||||
// TODO: needed? Since i kept the linebreaks, i could just use column and line to get the absolute position
|
||||
// via let res = &self.raw_lines[line - 1][col..(col + len)]; (or first char - would be enough)
|
||||
// and res.as_ptr() as usize - self.raw.as_ptr() as usize,
|
||||
_removed_data: RemovedHandler,
|
||||
}
|
||||
impl<'a> YamlWrapper<'a> {
|
||||
pub fn new(raw: &'a str) -> Self {
|
||||
let ((yaml, location_map), removed_data) = Self::parse_yaml(raw);
|
||||
let raw_lines = raw.lines().collect();
|
||||
Self {
|
||||
raw,
|
||||
|
||||
impl<'a> TryFrom<&'a str> for YamlWrapper<'a> {
|
||||
type Error = NonYamlError;
|
||||
|
||||
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
|
||||
let ((yaml, location_map), removed_data) = Self::parse_yaml(value)?;
|
||||
let raw_lines = value.lines().collect();
|
||||
Ok(Self {
|
||||
raw: value,
|
||||
_removed_data: removed_data,
|
||||
raw_lines,
|
||||
yaml,
|
||||
location_map,
|
||||
validation_result: Vec::new(),
|
||||
marker_map: Vec::new(),
|
||||
}
|
||||
_marker_map: Vec::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> YamlWrapper<'a> {
|
||||
fn get_pos_in_raw(&self, line: usize, col: usize) -> usize {
|
||||
let lines = &self.raw_lines;
|
||||
|
||||
if line > lines.len() - 1 {
|
||||
return self.raw.len() - 1;
|
||||
if line > lines.len() {
|
||||
return self.raw.len() - 2;
|
||||
}
|
||||
|
||||
let line_to_find_in = lines[line - 1];
|
||||
@ -57,32 +64,38 @@ impl<'a> YamlWrapper<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_yaml(raw: &'a str) -> ((Yaml, Mark), RemovedHandler) {
|
||||
fn parse_yaml(raw: &'a str) -> Result<((Yaml, Mark), RemovedHandler), NonYamlError> {
|
||||
let mut iter_handler = IterHandler::new(raw);
|
||||
|
||||
let parsed_data = ParLoader::load_from_iter(iter_handler.comment_removed_iter())
|
||||
.unwrap()
|
||||
let parsed_data = ParLoader::load_from_iter(iter_handler.comment_removed_iter())?
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap();
|
||||
.ok_or(NonYamlError::NoYamlFound)?;
|
||||
let positions = iter_handler.removed().to_vec();
|
||||
(parsed_data, positions.into())
|
||||
Ok((parsed_data, positions.into()))
|
||||
}
|
||||
|
||||
pub fn validate_yml<'b: 'a>(&mut self, context: &'b SchemaCache<'b>) {
|
||||
pub fn validate_yml<'b: 'a>(
|
||||
&mut self,
|
||||
context: &SchemaCache<'b>,
|
||||
) -> Vec<(usize, usize, ValidationError)> {
|
||||
let validation_result = context.validate_yaml(&self.yaml);
|
||||
if let Err(e) = validation_result {
|
||||
self.validation_result = e;
|
||||
}
|
||||
|
||||
self.construct_marker_map();
|
||||
self.construct_marker_map()
|
||||
}
|
||||
|
||||
fn get_range_for_scalar(&self, scalar: &Mark) -> (usize, usize) {
|
||||
assert!(matches!(scalar, Mark::Scalar(_, _)));
|
||||
let (line, col, len) = scalar.get_first_token_range();
|
||||
info!(
|
||||
"First token in range Line: {:?}, Col: {:?}, Len: {:?}",
|
||||
line, col, len
|
||||
);
|
||||
let index = self.get_pos_in_raw(line, col);
|
||||
(index, index + len)
|
||||
(index, (index + len).min(self.raw.len()))
|
||||
}
|
||||
|
||||
fn traverse_path<'b>(
|
||||
@ -121,28 +134,35 @@ impl<'a> YamlWrapper<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn construct_marker_map(&mut self) {
|
||||
for e in self.validation_result.iter() {
|
||||
let mut cloned_path = e.path().clone();
|
||||
if cloned_path.empty() {
|
||||
println!("highlighting first characters?");
|
||||
// TODO: think of sth else
|
||||
self.marker_map.push((0, 1, e.src().clone()));
|
||||
continue;
|
||||
}
|
||||
let mut yaml = &self.yaml;
|
||||
let mut marker = &self.location_map;
|
||||
let mut current_segment = cloned_path.shift().unwrap();
|
||||
while !cloned_path.empty() {
|
||||
(_, marker, yaml) = Self::traverse_path(current_segment, yaml, marker);
|
||||
current_segment = cloned_path.shift().unwrap();
|
||||
}
|
||||
fn construct_marker_map(&self) -> Vec<(usize, usize, ValidationError)> {
|
||||
self.validation_result
|
||||
.iter()
|
||||
.map(|e| {
|
||||
let mut cloned_path = e.path().clone();
|
||||
info!("Path: {:?}; Handling: {:?}", cloned_path, e);
|
||||
if cloned_path.empty() {
|
||||
info!("{:?} highlighting first characters?", e);
|
||||
// TODO: think of sth else
|
||||
(0, 1, e.src().clone())
|
||||
} else {
|
||||
let mut yaml = &self.yaml;
|
||||
let mut marker = &self.location_map;
|
||||
let mut current_segment = cloned_path.shift().unwrap();
|
||||
while !cloned_path.empty() {
|
||||
(_, marker, yaml) = Self::traverse_path(current_segment, yaml, marker);
|
||||
current_segment = cloned_path.shift().unwrap();
|
||||
}
|
||||
|
||||
(marker, _, _) = Self::traverse_path(current_segment, yaml, marker);
|
||||
|
||||
let position = self.get_range_for_scalar(marker);
|
||||
self.marker_map
|
||||
.push((position.0, position.1, e.src().clone()));
|
||||
}
|
||||
(marker, _, _) = Self::traverse_path(current_segment, yaml, marker);
|
||||
info!(
|
||||
"{:?} highlighting scalar- len: {:?}",
|
||||
marker,
|
||||
self.raw.len()
|
||||
);
|
||||
let position = self.get_range_for_scalar(marker);
|
||||
(position.0, position.1, e.src().clone())
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
pub mod add_err;
|
||||
pub mod code;
|
||||
pub mod error;
|
||||
pub mod input;
|
||||
pub mod log_helper;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use log::info;
|
||||
use yaml_rust2::{
|
||||
parser::{MarkedEventReceiver, Parser},
|
||||
scanner::Marker,
|
||||
@ -72,6 +73,16 @@ spam:
|
||||
foom
|
||||
"#;
|
||||
|
||||
const add_kw: &str = r#"id: DEMO.administration
|
||||
objectType: pageContainer
|
||||
data:
|
||||
variables:
|
||||
tes:
|
||||
type: string
|
||||
value: "test"
|
||||
pi: d
|
||||
"#;
|
||||
|
||||
const COMMENT_TEST: &str = r#"
|
||||
key1: \#value1
|
||||
key2: "this is # not a comment"
|
||||
@ -127,6 +138,45 @@ const INCOMPLETE_YAML: &str = r#"data:
|
||||
type: string
|
||||
value: TEST"#;
|
||||
|
||||
fn test_with_page_for_str(content: &str) {
|
||||
let schemas_to_parse = SCHEMA_PATHS;
|
||||
|
||||
let schemas = schemas_to_parse
|
||||
.iter()
|
||||
.map(|path| {
|
||||
(
|
||||
file_to_name(path),
|
||||
YamlLoader::load_from_str(&Reader::from_file(path).unwrap()).unwrap(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut storage = storage::SchemaCache::new();
|
||||
|
||||
for (nam, yaml) in &schemas {
|
||||
let n = yaml.len();
|
||||
if yaml.len() != 1 {
|
||||
panic!("only one document per file is allowed - found {n} in {nam}");
|
||||
}
|
||||
let parsed_schema: Result<Schema, _> = (&yaml[0]).try_into();
|
||||
storage.add_schema(nam, parsed_schema.unwrap());
|
||||
}
|
||||
|
||||
let mut wrapper = YamlWrapper::try_from(content).unwrap();
|
||||
let error = wrapper.validate_yml(&storage);
|
||||
|
||||
for (st, en, err) in error {
|
||||
info!("Error:({}, {}) {:?}", st, en, err);
|
||||
println!(
|
||||
"Pos: ({:?}..{:?}) = ({:?}: Error: {:?}",
|
||||
st,
|
||||
en,
|
||||
&content[st..en],
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EventSink {
|
||||
events: Vec<(Event, Marker)>,
|
||||
loader: YamlLoader,
|
||||
@ -140,7 +190,8 @@ impl MarkedEventReceiver for EventSink {
|
||||
|
||||
pub fn do_sth() {
|
||||
//com();
|
||||
my_own();
|
||||
//my_own();
|
||||
test_with_page_for_str(add_kw);
|
||||
}
|
||||
|
||||
fn com() {
|
||||
@ -171,7 +222,7 @@ pub fn my_own() {
|
||||
// panic!("stop");
|
||||
let schema = SCHEMA;
|
||||
let schemas_to_parse = SCHEMA_MATCH;
|
||||
let mut wrapper = YamlWrapper::new(schemas_to_parse);
|
||||
let mut wrapper = YamlWrapper::try_from(schemas_to_parse).unwrap();
|
||||
let schema_yaml = YamlLoader::load_from_str(schema).unwrap()[0].clone();
|
||||
let schema_onj = (&schema_yaml).try_into().unwrap();
|
||||
let name = "page.schema.json";
|
||||
@ -206,8 +257,8 @@ fn my_own5() {
|
||||
|
||||
let test_yaml_paths = vec![TEST[0]];
|
||||
for test_yaml_path in test_yaml_paths {
|
||||
let content = &Reader::from_file(test_yaml_path).unwrap();
|
||||
let mut wrapper = YamlWrapper::new(content);
|
||||
let content = Reader::from_file(test_yaml_path).unwrap();
|
||||
let mut wrapper = YamlWrapper::try_from(content.as_str()).unwrap();
|
||||
wrapper.validate_yml(&storage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@ use wasm_bindgen::prelude::wasm_bindgen;
|
||||
use yaml_rust2::{Yaml, YamlLoader};
|
||||
|
||||
use crate::{
|
||||
code::highlight::HighlightError,
|
||||
input::wrapper::YamlWrapper,
|
||||
read::{file_to_name, Reader, SCHEMA_PATHS},
|
||||
schema::storage::{self, SchemaCache},
|
||||
};
|
||||
@ -31,7 +33,7 @@ pub fn load_context() {
|
||||
.map(|path| {
|
||||
(
|
||||
file_to_name(path),
|
||||
YamlLoader::load_from_str(&Reader::from_file(path).unwrap()).unwrap(),
|
||||
YamlLoader::load_from_str(&Reader::from_file_mock(path).unwrap()).unwrap(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@ -50,35 +52,25 @@ pub fn load_context() {
|
||||
|
||||
let mut context = CONTEXT.lock().unwrap();
|
||||
*context = Some(storage);
|
||||
console_log("context loaded");
|
||||
info!("context loaded");
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn get_highlighting(yaml: &str) {
|
||||
if let Some(test_yaml) = construct_yaml(yaml) {
|
||||
let context = CONTEXT.lock().unwrap();
|
||||
let val_res = context.as_ref().unwrap().validate_yaml(&test_yaml);
|
||||
match val_res {
|
||||
Ok(_) => debug!("Valid"),
|
||||
Err(e) => {
|
||||
for err in e {
|
||||
info!("{:?}", err);
|
||||
}
|
||||
}
|
||||
pub fn get_highlighting(yaml: &str) -> Vec<HighlightError> {
|
||||
if let Ok(mut test_yaml) = YamlWrapper::try_from(yaml) {
|
||||
if CONTEXT.lock().unwrap().is_none() {
|
||||
error!("Context not loaded");
|
||||
load_context();
|
||||
//return Vec::new();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn construct_yaml(input: &str) -> Option<Yaml> {
|
||||
let yaml = YamlLoader::load_from_str(input)
|
||||
.inspect_err(|e| {
|
||||
error!("{:?}", e);
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
if yaml.is_empty() {
|
||||
None
|
||||
let context_guard = CONTEXT.lock().unwrap();
|
||||
test_yaml
|
||||
.validate_yml(context_guard.as_ref().unwrap())
|
||||
.into_iter()
|
||||
.map(|e| e.into())
|
||||
.collect()
|
||||
} else {
|
||||
Some(yaml[0].clone())
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user