lib.rs 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. extern crate proc_macro;
  2. use anchor_syn::codegen::error as error_codegen;
  3. use anchor_syn::parser::error as error_parser;
  4. use anchor_syn::ErrorArgs;
  5. use syn::parse_macro_input;
  6. /// Generates `Error` and `type Result<T> = Result<T, Error>` types to be
  7. /// used as return types from Anchor instruction handlers. Importantly, the
  8. /// attribute implements
  9. /// [`From`](https://doc.rust-lang.org/std/convert/trait.From.html) on the
  10. /// `ErrorCode` to support converting from the user defined error enum *into*
  11. /// the generated `Error`.
  12. ///
  13. /// # Example
  14. ///
  15. /// ```ignore
  16. /// use anchor_lang::prelude::*;
  17. ///
  18. /// #[program]
  19. /// mod errors {
  20. /// use super::*;
  21. /// pub fn hello(_ctx: Context<Hello>) -> Result<()> {
  22. /// Err(MyError::Hello.into())
  23. /// }
  24. /// }
  25. ///
  26. /// #[derive(Accounts)]
  27. /// pub struct Hello {}
  28. ///
  29. /// #[error]
  30. /// pub enum MyError {
  31. /// #[msg("This is an error message clients will automatically display")]
  32. /// Hello,
  33. /// }
  34. /// ```
  35. ///
  36. /// Note that we generate a new `Error` type so that we can return either the
  37. /// user defined error enum *or* a
  38. /// [`ProgramError`](../solana_program/enum.ProgramError.html), which is used
  39. /// pervasively, throughout solana program crates. The generated `Error` type
  40. /// should almost never be used directly, as the user defined error is
  41. /// preferred. In the example above, `MyError::Hello.into()`.
  42. ///
  43. /// # Msg
  44. ///
  45. /// The `#[msg(..)]` attribute is inert, and is used only as a marker so that
  46. /// parsers and IDLs can map error codes to error messages.
  47. #[proc_macro_attribute]
  48. pub fn error(
  49. args: proc_macro::TokenStream,
  50. input: proc_macro::TokenStream,
  51. ) -> proc_macro::TokenStream {
  52. let args = match args.is_empty() {
  53. true => None,
  54. false => Some(parse_macro_input!(args as ErrorArgs)),
  55. };
  56. let mut error_enum = parse_macro_input!(input as syn::ItemEnum);
  57. let error = error_codegen::generate(error_parser::parse(&mut error_enum, args));
  58. proc_macro::TokenStream::from(error)
  59. }