interperter.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. use dioxus_core::{Attribute, AttributeValue, NodeFactory, VNode};
  2. use dioxus_rsx::{BodyNode, CallBody, ElementAttr, IfmtInput, Segment};
  3. use quote::ToTokens;
  4. use quote::__private::Span;
  5. use std::str::FromStr;
  6. use syn::{parse2, parse_str, Expr};
  7. use crate::attributes::attrbute_to_static_str;
  8. use crate::captuered_context::{CapturedContext, IfmtArgs};
  9. use crate::elements::element_to_static_str;
  10. use crate::error::{Error, ParseError, RecompileReason};
  11. fn resolve_ifmt(ifmt: &IfmtInput, captured: &IfmtArgs) -> Result<String, Error> {
  12. let mut result = String::new();
  13. for seg in &ifmt.segments {
  14. match seg {
  15. Segment::Formatted {
  16. segment,
  17. format_args,
  18. } => {
  19. let expr = segment.to_token_stream();
  20. let expr: Expr = parse2(expr).unwrap();
  21. let search = captured.named_args.iter().find(|fmted| {
  22. parse_str::<Expr>(fmted.expr).unwrap() == expr
  23. && fmted.format_args == format_args
  24. });
  25. match search {
  26. Some(formatted) => {
  27. result.push_str(&formatted.result);
  28. }
  29. None => {
  30. let expr_str = segment.to_token_stream().to_string();
  31. return Err(Error::RecompileRequiredError(
  32. RecompileReason::CapturedExpression(format!(
  33. "could not resolve {{{}:{}}}",
  34. expr_str, format_args
  35. )),
  36. ));
  37. }
  38. }
  39. }
  40. Segment::Literal(lit) => result.push_str(lit),
  41. }
  42. }
  43. Ok(result)
  44. }
  45. pub fn build<'a>(
  46. rsx: CallBody,
  47. mut ctx: CapturedContext<'a>,
  48. factory: &NodeFactory<'a>,
  49. ) -> Result<VNode<'a>, Error> {
  50. let children_built = factory.bump().alloc(Vec::new());
  51. for child in rsx.roots {
  52. children_built.push(build_node(child, &mut ctx, factory)?);
  53. }
  54. if children_built.len() == 1 {
  55. Ok(children_built.pop().unwrap())
  56. } else {
  57. Ok(factory.fragment_from_iter(children_built.iter()))
  58. }
  59. }
  60. fn build_node<'a>(
  61. node: BodyNode,
  62. ctx: &mut CapturedContext<'a>,
  63. factory: &NodeFactory<'a>,
  64. ) -> Result<VNode<'a>, Error> {
  65. let bump = factory.bump();
  66. match node {
  67. BodyNode::Text(text) => {
  68. let ifmt = IfmtInput::from_str(&text.value())
  69. .map_err(|err| Error::ParseError(ParseError::new(err, ctx.location.clone())))?;
  70. let text = bump.alloc(resolve_ifmt(&ifmt, &ctx.captured)?);
  71. Ok(factory.text(format_args!("{}", text)))
  72. }
  73. BodyNode::Element(el) => {
  74. let attributes: &mut Vec<Attribute> = bump.alloc(Vec::new());
  75. for attr in &el.attributes {
  76. match &attr.attr {
  77. ElementAttr::AttrText { .. } | ElementAttr::CustomAttrText { .. } => {
  78. let (name, value, span): (String, IfmtInput, Span) = match &attr.attr {
  79. ElementAttr::AttrText { name, value } => (
  80. name.to_string(),
  81. IfmtInput::from_str(&value.value()).map_err(|err| {
  82. Error::ParseError(ParseError::new(err, ctx.location.clone()))
  83. })?,
  84. name.span(),
  85. ),
  86. ElementAttr::CustomAttrText { name, value } => (
  87. name.value(),
  88. IfmtInput::from_str(&value.value()).map_err(|err| {
  89. Error::ParseError(ParseError::new(err, ctx.location.clone()))
  90. })?,
  91. name.span(),
  92. ),
  93. _ => unreachable!(),
  94. };
  95. if let Some((name, namespace)) = attrbute_to_static_str(&name) {
  96. let value = bump.alloc(resolve_ifmt(&value, &ctx.captured)?);
  97. attributes.push(Attribute {
  98. name,
  99. value: AttributeValue::Text(value),
  100. is_static: true,
  101. is_volatile: false,
  102. namespace,
  103. });
  104. } else {
  105. return Err(Error::ParseError(ParseError::new(
  106. syn::Error::new(span, format!("unknown attribute: {}", name)),
  107. ctx.location.clone(),
  108. )));
  109. }
  110. }
  111. ElementAttr::AttrExpression { .. }
  112. | ElementAttr::CustomAttrExpression { .. } => {
  113. let (name, value) = match &attr.attr {
  114. ElementAttr::AttrExpression { name, value } => {
  115. (name.to_string(), value)
  116. }
  117. ElementAttr::CustomAttrExpression { name, value } => {
  118. (name.value(), value)
  119. }
  120. _ => unreachable!(),
  121. };
  122. if let Some((_, resulting_value)) = ctx
  123. .expressions
  124. .iter()
  125. .find(|(n, _)| parse_str::<Expr>(*n).unwrap() == *value)
  126. {
  127. if let Some((name, namespace)) = attrbute_to_static_str(&name) {
  128. let value = bump.alloc(resulting_value.clone());
  129. attributes.push(Attribute {
  130. name,
  131. value: AttributeValue::Text(value),
  132. is_static: true,
  133. is_volatile: false,
  134. namespace,
  135. });
  136. }
  137. } else {
  138. return Err(Error::RecompileRequiredError(
  139. RecompileReason::CapturedExpression(
  140. value.into_token_stream().to_string(),
  141. ),
  142. ));
  143. }
  144. }
  145. _ => (),
  146. };
  147. }
  148. let children = bump.alloc(Vec::new());
  149. for child in el.children {
  150. let node = build_node(child, ctx, factory)?;
  151. children.push(node);
  152. }
  153. let listeners = bump.alloc(Vec::new());
  154. for attr in el.attributes {
  155. if let ElementAttr::EventTokens { .. } = attr.attr {
  156. let expr: Expr = parse2(attr.to_token_stream()).map_err(|err| {
  157. Error::ParseError(ParseError::new(err, ctx.location.clone()))
  158. })?;
  159. if let Some(idx) = ctx.listeners.iter().position(|(code, _)| {
  160. if let Ok(parsed) = parse_str::<Expr>(*code) {
  161. parsed == expr
  162. } else {
  163. false
  164. }
  165. }) {
  166. let (_, listener) = ctx.listeners.remove(idx);
  167. listeners.push(listener)
  168. } else {
  169. return Err(Error::RecompileRequiredError(
  170. RecompileReason::CapturedListener(expr.to_token_stream().to_string()),
  171. ));
  172. }
  173. }
  174. }
  175. let tag = bump.alloc(el.name.to_string());
  176. if let Some((tag, ns)) = element_to_static_str(tag) {
  177. match el.key {
  178. None => Ok(factory.raw_element(
  179. tag,
  180. ns,
  181. listeners,
  182. attributes.as_slice(),
  183. children.as_slice(),
  184. None,
  185. )),
  186. Some(lit) => {
  187. let ifmt: IfmtInput = parse_str(&lit.value()).map_err(|err| {
  188. Error::ParseError(ParseError::new(err, ctx.location.clone()))
  189. })?;
  190. let key = bump.alloc(resolve_ifmt(&ifmt, &ctx.captured)?);
  191. Ok(factory.raw_element(
  192. tag,
  193. ns,
  194. listeners,
  195. attributes.as_slice(),
  196. children.as_slice(),
  197. Some(format_args!("{}", key)),
  198. ))
  199. }
  200. }
  201. } else {
  202. Err(Error::ParseError(ParseError::new(
  203. syn::Error::new(el.name.span(), format!("unknown element: {}", tag)),
  204. ctx.location.clone(),
  205. )))
  206. }
  207. }
  208. BodyNode::Component(comp) => {
  209. let expr: Expr = parse2(comp.to_token_stream())
  210. .map_err(|err| Error::ParseError(ParseError::new(err, ctx.location.clone())))?;
  211. if let Some(idx) = ctx.components.iter().position(|(code, _)| {
  212. if let Ok(parsed) = parse_str::<Expr>(*code) {
  213. parsed == expr
  214. } else {
  215. false
  216. }
  217. }) {
  218. let (_, vnode) = ctx.components.remove(idx);
  219. Ok(vnode)
  220. } else {
  221. Err(Error::RecompileRequiredError(
  222. RecompileReason::CapturedComponent(comp.name.to_token_stream().to_string()),
  223. ))
  224. }
  225. }
  226. BodyNode::RawExpr(iterator) => {
  227. if let Some(idx) = ctx.iterators.iter().position(|(code, _)| {
  228. if let Ok(parsed) = parse_str::<Expr>(*code) {
  229. parsed == iterator
  230. } else {
  231. false
  232. }
  233. }) {
  234. let (_, vnode) = ctx.iterators.remove(idx);
  235. Ok(vnode)
  236. } else {
  237. Err(Error::RecompileRequiredError(
  238. RecompileReason::CapturedExpression(iterator.to_token_stream().to_string()),
  239. ))
  240. }
  241. }
  242. }
  243. }