prettier_please.rs 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. use prettyplease::unparse;
  2. use syn::{Expr, File, Item};
  3. /// Unparse an expression back into a string
  4. ///
  5. /// This creates a new temporary file, parses the expression into it, and then formats the file.
  6. /// This is a bit of a hack, but dtonlay doesn't want to support this very simple usecase, forcing us to clone the expr
  7. pub fn unparse_expr(expr: &Expr) -> String {
  8. let file = wrapped(expr);
  9. let wrapped = unparse(&file);
  10. unwrapped(wrapped)
  11. }
  12. // Split off the fn main and then cut the tabs off the front
  13. fn unwrapped(raw: String) -> String {
  14. let mut o = raw
  15. .strip_prefix("fn main() {\n")
  16. .unwrap()
  17. .strip_suffix("}\n")
  18. .unwrap()
  19. .lines()
  20. .map(|line| line.strip_prefix(" ").unwrap()) // todo: set this to tab level
  21. .collect::<Vec<_>>()
  22. .join("\n");
  23. // remove the semicolon
  24. o.pop();
  25. o
  26. }
  27. fn wrapped(expr: &Expr) -> File {
  28. File {
  29. shebang: None,
  30. attrs: vec![],
  31. items: vec![
  32. //
  33. Item::Verbatim(quote::quote! {
  34. fn main() {
  35. #expr;
  36. }
  37. }),
  38. ],
  39. }
  40. }
  41. #[test]
  42. fn unparses_raw() {
  43. let expr = syn::parse_str("1 + 1").unwrap();
  44. let unparsed = unparse(&wrapped(&expr));
  45. assert_eq!(unparsed, "fn main() {\n 1 + 1;\n}\n");
  46. }
  47. #[test]
  48. fn unparses_completely() {
  49. let expr = syn::parse_str("1 + 1").unwrap();
  50. let unparsed = unparse_expr(&expr);
  51. assert_eq!(unparsed, "1 + 1");
  52. }
  53. #[test]
  54. fn unparses_let_guard() {
  55. let expr = syn::parse_str("let Some(url) = &link.location").unwrap();
  56. let unparsed = unparse_expr(&expr);
  57. assert_eq!(unparsed, "let Some(url) = &link.location");
  58. }
  59. #[test]
  60. fn weird_ifcase() {
  61. let contents = r##"
  62. fn main() {
  63. move |_| timer.with_mut(|t| if t.started_at.is_none() { Some(Instant::now()) } else { None })
  64. }
  65. "##;
  66. let expr: File = syn::parse_file(contents).unwrap();
  67. let out = unparse(&expr);
  68. println!("{}", out);
  69. }