rstml/node/
node_value.rs

1//!
2//!  Node value type
3use std::convert::TryFrom;
4
5use proc_macro2::TokenStream;
6use syn::{token::Brace, Block};
7
8#[derive(Clone, Debug, syn_derive::ToTokens, syn_derive::Parse)]
9pub struct InvalidBlock {
10    #[syn(braced)]
11    pub brace: Brace,
12    #[syn(in = brace)]
13    pub body: TokenStream,
14}
15
16/// Block node.
17///
18/// Arbitrary rust code in braced `{}` blocks.
19#[derive(Clone, Debug, syn_derive::ToTokens)]
20pub enum NodeBlock {
21    /// The block value..
22    ValidBlock(Block),
23
24    Invalid(InvalidBlock),
25}
26
27impl NodeBlock {
28    ///
29    /// Returns syntactically valid `syn::Block` of Rust code.
30    ///
31    /// Usually to make macro expansion IDE friendly, its better to use
32    /// `ToTokens` instead. Because it also emit blocks that is invalid for
33    /// syn, but valid for rust and rust analyzer. But if you need early
34    /// checks that this block is valid  - use this method.
35    ///
36    /// Example of blocks that will or will not parse:
37    /// ```no_compile
38    /// {x.} // Rust will parse this syntax, but for syn this is invalid Block, because after dot ident is expected.
39    ///      // Emiting code like this for rust analyzer allows it to find completion.
40    ///      // This block is parsed as NodeBlock::Invalid
41    /// {]}   // this is invalid syntax for rust compiler and rust analyzer so it will not be parsed at all.
42    /// {x + y} // Valid syn Block, parsed as NodeBlock::Valid
43    /// ```
44    pub fn try_block(&self) -> Option<&Block> {
45        match self {
46            Self::ValidBlock(b) => Some(b),
47            Self::Invalid(_) => None,
48        }
49    }
50}
51
52impl TryFrom<NodeBlock> for Block {
53    type Error = syn::Error;
54    fn try_from(v: NodeBlock) -> Result<Block, Self::Error> {
55        match v {
56            NodeBlock::ValidBlock(v) => Ok(v),
57            NodeBlock::Invalid(_) => Err(syn::Error::new_spanned(
58                v,
59                "Cant parse expression as block.",
60            )),
61        }
62    }
63}