Skip to content

Commit e5b7f3c

Browse files
committed
Fix: use config and diagnostc from invalid_block in attribute place.
Also add tests and remove unused structure.
1 parent 4a1cffa commit e5b7f3c

File tree

4 files changed

+73
-28
lines changed

4 files changed

+73
-28
lines changed

src/node/attribute.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,6 @@ impl AttributeValueExpr {
6868
}
6969
}
7070

71-
#[derive(Clone, Debug, syn_derive::ToTokens)]
72-
pub struct AttributeValueBlock {
73-
pub token_eq: Token![=],
74-
pub value: NodeBlock,
75-
}
76-
7771
#[derive(Clone, Debug, syn_derive::ToTokens)]
7872
pub enum KeyedAttributeValue {
7973
Binding(FnBinding),
@@ -263,7 +257,8 @@ impl ParseRecoverable for KeyedAttribute {
263257
KVAttributeValue::Expr(parse_quote!(#vbl))
264258
}
265259

266-
Err(_) if input.fork().peek(Brace) => {
260+
Err(err) if input.fork().peek(Brace) && parser.config().recover_block => {
261+
parser.push_diagnostic(err);
267262
let ivb = parser.parse_simple(input)?;
268263
KVAttributeValue::InvalidBraced(ivb)
269264
}

src/node/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ mod parser_ext;
1616
mod raw_text;
1717

1818
pub use attribute::{
19-
AttributeValueBlock, AttributeValueExpr, FnBinding, KVAttributeValue, KeyedAttribute,
20-
KeyedAttributeValue, NodeAttribute,
19+
AttributeValueExpr, FnBinding, KVAttributeValue, KeyedAttribute, KeyedAttributeValue,
20+
NodeAttribute,
2121
};
2222
pub use node_name::{NodeName, NodeNameFragment};
2323
pub use node_value::{InvalidBlock, NodeBlock};

src/visitor.rs

-17
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,6 @@ pub trait Visitor<Custom> {
9191
) -> bool {
9292
true
9393
}
94-
fn visit_attribute_block(
95-
&mut self,
96-
_key: &mut NodeName,
97-
_value: &mut AttributeValueBlock,
98-
) -> bool {
99-
true
100-
}
10194
}
10295

10396
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Ord, Copy, Eq)]
@@ -378,16 +371,6 @@ where
378371
KVAttributeValue::InvalidBraced(braced) => self.visit_invalid_block(braced),
379372
}
380373
}
381-
fn visit_attribute_block(
382-
&mut self,
383-
key: &mut NodeName,
384-
value: &mut AttributeValueBlock,
385-
) -> bool {
386-
visit_inner!(self.visitor.visit_attribute_block(key, value));
387-
388-
self.visit_node_name(key);
389-
self.visit_block(&mut value.value)
390-
}
391374

392375
fn visit_invalid_block(&mut self, block: &mut InvalidBlock) -> bool {
393376
visit_inner!(self.visitor.visit_invalid_block(block));

tests/test.rs

+69-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use proc_macro2::TokenStream;
55
use quote::{quote, ToTokens};
66
use rstml::{
77
node::{
8-
CustomNode, KeyedAttribute, KeyedAttributeValue, Node, NodeAttribute, NodeElement,
9-
NodeName, NodeType,
8+
CustomNode, KVAttributeValue, KeyedAttribute, KeyedAttributeValue, Node, NodeAttribute,
9+
NodeElement, NodeName, NodeType,
1010
},
1111
parse2,
1212
recoverable::{ParseRecoverable, RecoverableContext},
@@ -974,6 +974,73 @@ fn test_single_element_with_different_attributes() -> Result<()> {
974974
Ok(())
975975
}
976976

977+
#[test]
978+
fn test_invalid_blocks() -> Result<()> {
979+
// test that invalid blocks can be parsed in recoverable mode
980+
// usefull for IDEs
981+
let tokens = quote! {
982+
<foo>{block.} </foo>
983+
};
984+
985+
let config = ParserConfig::new().recover_block(true);
986+
let (nodes, diagnostics) = Parser::new(config)
987+
.parse_recoverable(tokens.clone())
988+
.split_vec();
989+
990+
let Node::Block(block) = get_element_child(&nodes, 0, 0) else {
991+
panic!("expected block")
992+
};
993+
994+
assert_eq!(block.to_token_stream().to_string(), "{ block . }");
995+
assert_eq!(diagnostics.len(), 1);
996+
let dbg_diag = format!("{:?}", diagnostics[0]);
997+
assert!(dbg_diag.contains("unexpected end of input, expected identifier or integer"));
998+
// same should not work if recover_block = false
999+
let config = ParserConfig::new();
1000+
let (nodes, diagnostics) = Parser::new(config).parse_recoverable(tokens).split_vec();
1001+
let node = get_element(&nodes, 0);
1002+
assert!(node.children.is_empty());
1003+
// TODO: Cleanup errors
1004+
assert!(diagnostics.len() > 1);
1005+
Ok(())
1006+
}
1007+
1008+
#[test]
1009+
fn test_invalid_blocks_in_attr() -> Result<()> {
1010+
// test that invalid blocks can be parsed in recoverable mode
1011+
// usefull for IDEs
1012+
let tokens = quote! {
1013+
<foo foo={block.}> </foo>
1014+
};
1015+
1016+
let config = ParserConfig::new().recover_block(true);
1017+
let (nodes, diagnostics) = Parser::new(config)
1018+
.parse_recoverable(tokens.clone())
1019+
.split_vec();
1020+
1021+
let attr = get_element_attribute(&nodes, 0, 0);
1022+
let KeyedAttributeValue::Value(eq_val) = &attr.possible_value else {
1023+
panic!("expected value")
1024+
};
1025+
1026+
let KVAttributeValue::InvalidBraced(block) = &eq_val.value else {
1027+
panic!("expected invalid block")
1028+
};
1029+
1030+
assert_eq!(block.to_token_stream().to_string(), "{ block . }");
1031+
1032+
assert_eq!(diagnostics.len(), 1);
1033+
let dbg_diag = format!("{:?}", diagnostics[0]);
1034+
assert!(dbg_diag.contains("unexpected end of input, expected identifier or integer"));
1035+
// same should not work if recover_block = false
1036+
let config = ParserConfig::new();
1037+
let (nodes, diagnostics) = Parser::new(config).parse_recoverable(tokens).split_vec();
1038+
let node = get_element(&nodes, 0);
1039+
assert!(node.attributes().is_empty());
1040+
assert_eq!(diagnostics.len(), 1);
1041+
Ok(())
1042+
}
1043+
9771044
#[test]
9781045
fn test_empty_input() -> Result<()> {
9791046
let tokens = quote! {};

0 commit comments

Comments
 (0)