From e5b7f3c22fdc568b184d94be47e378043fa76945 Mon Sep 17 00:00:00 2001 From: Vladimir Motylenko Date: Sat, 27 Jul 2024 17:34:50 +0300 Subject: [PATCH] Fix: use config and diagnostc from invalid_block in attribute place. Also add tests and remove unused structure. --- src/node/attribute.rs | 9 ++---- src/node/mod.rs | 4 +-- src/visitor.rs | 17 ----------- tests/test.rs | 71 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 73 insertions(+), 28 deletions(-) diff --git a/src/node/attribute.rs b/src/node/attribute.rs index f4c6b11..2334d8e 100644 --- a/src/node/attribute.rs +++ b/src/node/attribute.rs @@ -68,12 +68,6 @@ impl AttributeValueExpr { } } -#[derive(Clone, Debug, syn_derive::ToTokens)] -pub struct AttributeValueBlock { - pub token_eq: Token![=], - pub value: NodeBlock, -} - #[derive(Clone, Debug, syn_derive::ToTokens)] pub enum KeyedAttributeValue { Binding(FnBinding), @@ -263,7 +257,8 @@ impl ParseRecoverable for KeyedAttribute { KVAttributeValue::Expr(parse_quote!(#vbl)) } - Err(_) if input.fork().peek(Brace) => { + Err(err) if input.fork().peek(Brace) && parser.config().recover_block => { + parser.push_diagnostic(err); let ivb = parser.parse_simple(input)?; KVAttributeValue::InvalidBraced(ivb) } diff --git a/src/node/mod.rs b/src/node/mod.rs index ba96560..949d449 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -16,8 +16,8 @@ mod parser_ext; mod raw_text; pub use attribute::{ - AttributeValueBlock, AttributeValueExpr, FnBinding, KVAttributeValue, KeyedAttribute, - KeyedAttributeValue, NodeAttribute, + AttributeValueExpr, FnBinding, KVAttributeValue, KeyedAttribute, KeyedAttributeValue, + NodeAttribute, }; pub use node_name::{NodeName, NodeNameFragment}; pub use node_value::{InvalidBlock, NodeBlock}; diff --git a/src/visitor.rs b/src/visitor.rs index a80531f..f6d4226 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -91,13 +91,6 @@ pub trait Visitor { ) -> bool { true } - fn visit_attribute_block( - &mut self, - _key: &mut NodeName, - _value: &mut AttributeValueBlock, - ) -> bool { - true - } } #[derive(Debug, Default, Clone, PartialEq, PartialOrd, Ord, Copy, Eq)] @@ -378,16 +371,6 @@ where KVAttributeValue::InvalidBraced(braced) => self.visit_invalid_block(braced), } } - fn visit_attribute_block( - &mut self, - key: &mut NodeName, - value: &mut AttributeValueBlock, - ) -> bool { - visit_inner!(self.visitor.visit_attribute_block(key, value)); - - self.visit_node_name(key); - self.visit_block(&mut value.value) - } fn visit_invalid_block(&mut self, block: &mut InvalidBlock) -> bool { visit_inner!(self.visitor.visit_invalid_block(block)); diff --git a/tests/test.rs b/tests/test.rs index 79aaf32..d8e70da 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -5,8 +5,8 @@ use proc_macro2::TokenStream; use quote::{quote, ToTokens}; use rstml::{ node::{ - CustomNode, KeyedAttribute, KeyedAttributeValue, Node, NodeAttribute, NodeElement, - NodeName, NodeType, + CustomNode, KVAttributeValue, KeyedAttribute, KeyedAttributeValue, Node, NodeAttribute, + NodeElement, NodeName, NodeType, }, parse2, recoverable::{ParseRecoverable, RecoverableContext}, @@ -974,6 +974,73 @@ fn test_single_element_with_different_attributes() -> Result<()> { Ok(()) } +#[test] +fn test_invalid_blocks() -> Result<()> { + // test that invalid blocks can be parsed in recoverable mode + // usefull for IDEs + let tokens = quote! { + {block.} + }; + + let config = ParserConfig::new().recover_block(true); + let (nodes, diagnostics) = Parser::new(config) + .parse_recoverable(tokens.clone()) + .split_vec(); + + let Node::Block(block) = get_element_child(&nodes, 0, 0) else { + panic!("expected block") + }; + + assert_eq!(block.to_token_stream().to_string(), "{ block . }"); + assert_eq!(diagnostics.len(), 1); + let dbg_diag = format!("{:?}", diagnostics[0]); + assert!(dbg_diag.contains("unexpected end of input, expected identifier or integer")); + // same should not work if recover_block = false + let config = ParserConfig::new(); + let (nodes, diagnostics) = Parser::new(config).parse_recoverable(tokens).split_vec(); + let node = get_element(&nodes, 0); + assert!(node.children.is_empty()); + // TODO: Cleanup errors + assert!(diagnostics.len() > 1); + Ok(()) +} + +#[test] +fn test_invalid_blocks_in_attr() -> Result<()> { + // test that invalid blocks can be parsed in recoverable mode + // usefull for IDEs + let tokens = quote! { + + }; + + let config = ParserConfig::new().recover_block(true); + let (nodes, diagnostics) = Parser::new(config) + .parse_recoverable(tokens.clone()) + .split_vec(); + + let attr = get_element_attribute(&nodes, 0, 0); + let KeyedAttributeValue::Value(eq_val) = &attr.possible_value else { + panic!("expected value") + }; + + let KVAttributeValue::InvalidBraced(block) = &eq_val.value else { + panic!("expected invalid block") + }; + + assert_eq!(block.to_token_stream().to_string(), "{ block . }"); + + assert_eq!(diagnostics.len(), 1); + let dbg_diag = format!("{:?}", diagnostics[0]); + assert!(dbg_diag.contains("unexpected end of input, expected identifier or integer")); + // same should not work if recover_block = false + let config = ParserConfig::new(); + let (nodes, diagnostics) = Parser::new(config).parse_recoverable(tokens).split_vec(); + let node = get_element(&nodes, 0); + assert!(node.attributes().is_empty()); + assert_eq!(diagnostics.len(), 1); + Ok(()) +} + #[test] fn test_empty_input() -> Result<()> { let tokens = quote! {};