1
0

interperter.rs 12 KB

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