chore (backend-rs, macro-rs): separate error doc impl into another crate

This commit is contained in:
naskya 2024-08-18 02:49:38 +09:00
parent abb5636a4c
commit f423b277cc
No known key found for this signature in database
GPG key ID: 712D413B3A9FED5C
18 changed files with 38 additions and 105 deletions

12
Cargo.lock generated
View file

@ -213,6 +213,7 @@ dependencies = [
"chrono", "chrono",
"cuid2", "cuid2",
"emojis", "emojis",
"error-doc",
"futures-util", "futures-util",
"identicon-rs", "identicon-rs",
"idna 1.0.2", "idna 1.0.2",
@ -945,6 +946,17 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "error-doc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ffaad84523e0144697672bce3a0d8e300fd43404a630d420f238e2ef2e85b84"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.74",
]
[[package]] [[package]]
name = "etcetera" name = "etcetera"
version = "0.8.0" version = "0.8.0"

View file

@ -23,6 +23,7 @@ chrono = { version = "0.4.38", default-features = false }
convert_case = { version = "0.6.0", default-features = false } convert_case = { version = "0.6.0", default-features = false }
cuid2 = { version = "0.1.2", default-features = false } cuid2 = { version = "0.1.2", default-features = false }
emojis = { version = "0.6.3", default-features = false } emojis = { version = "0.6.3", default-features = false }
error-doc = { version = "0.1.0" }
futures-util = { version = "0.3.30", default-features = false } futures-util = { version = "0.3.30", default-features = false }
identicon-rs = "5.0.1" identicon-rs = "5.0.1"
idna = { version = "1.0.2", default-features = false } idna = { version = "1.0.2", default-features = false }

View file

@ -27,6 +27,7 @@ bcrypt = { workspace = true, features = ["std"] }
chrono = { workspace = true } chrono = { workspace = true }
cuid2 = { workspace = true } cuid2 = { workspace = true }
emojis = { workspace = true } emojis = { workspace = true }
error-doc = { workspace = true }
futures-util = { workspace = true, features = ["io"] } futures-util = { workspace = true, features = ["io"] }
identicon-rs = { workspace = true } identicon-rs = { workspace = true }
idna = { workspace = true, features = ["std", "compiled_data"] } idna = { workspace = true, features = ["std", "compiled_data"] }

View file

@ -9,10 +9,10 @@ use sea_orm::{ColumnTrait, DbErr, EntityTrait, QueryFilter, QuerySelect};
#[macros::errors] #[macros::errors]
pub enum Error { pub enum Error {
#[doc = "nonexistent note"] #[doc = "Nonexistent note"]
#[error("note {0} not found")] #[error("note {0} not found")]
NoteNotFound(String), NoteNotFound(String),
#[doc = "database error"] #[doc = "Database error"]
#[error(transparent)] #[error(transparent)]
Db(#[from] DbErr), Db(#[from] DbErr),
} }

View file

@ -12,7 +12,7 @@ pub enum Error {
#[error("@instance.actor not found")] #[error("@instance.actor not found")]
InstanceActorNotFound, InstanceActorNotFound,
#[error(transparent)] #[error(transparent)]
#[doc = "database error"] #[doc = "Database error"]
Db(#[from] DbErr), Db(#[from] DbErr),
} }

View file

@ -12,7 +12,7 @@ pub enum Error {
#[error("@relay.actor not found")] #[error("@relay.actor not found")]
RelayActorNotFound, RelayActorNotFound,
#[error(transparent)] #[error(transparent)]
#[doc = "database error"] #[doc = "Database error"]
Db(#[from] DbErr), Db(#[from] DbErr),
} }

View file

@ -14,7 +14,7 @@ pub enum Error {
HttpClient(#[from] http_client::Error), HttpClient(#[from] http_client::Error),
#[error("HTTP request failed")] #[error("HTTP request failed")]
Http(#[from] isahc::Error), Http(#[from] isahc::Error),
#[doc = "bad HTTP status"] #[doc = "Bad HTTP status"]
#[error("bad HTTP status ({0})")] #[error("bad HTTP status ({0})")]
BadStatus(String), BadStatus(String),
#[error("failed to parse HTTP response body as text")] #[error("failed to parse HTTP response body as text")]

View file

@ -145,7 +145,7 @@ pub async fn nodeinfo_2_0() -> Result<Nodeinfo20, DbErr> {
#[macros::for_ts] #[macros::for_ts]
#[macros::errors] #[macros::errors]
pub enum Error { pub enum Error {
#[doc = "database error"] #[doc = "Database error"]
#[error(transparent)] #[error(transparent)]
Db(#[from] DbErr), Db(#[from] DbErr),
#[error("failed to serialize nodeinfo into JSON")] #[error("failed to serialize nodeinfo into JSON")]

View file

@ -15,7 +15,7 @@ pub enum Error {
HttpClient(#[from] http_client::Error), HttpClient(#[from] http_client::Error),
#[error("HTTP request failed")] #[error("HTTP request failed")]
Isahc(#[from] isahc::Error), Isahc(#[from] isahc::Error),
#[doc = "bad HTTP status"] #[doc = "Bad HTTP status"]
#[error("bad HTTP status ({0})")] #[error("bad HTTP status ({0})")]
BadStatus(String), BadStatus(String),
#[error("failed to decode an image")] #[error("failed to decode an image")]
@ -24,10 +24,10 @@ pub enum Error {
Io(#[from] std::io::Error), Io(#[from] std::io::Error),
#[error("failed to extract the exif data")] #[error("failed to extract the exif data")]
Exif(#[from] nom_exif::Error), Exif(#[from] nom_exif::Error),
#[doc = "too many fetch attempts"] #[doc = "Too many fetch attempts"]
#[error("too many fetch attempts for {0}")] #[error("too many fetch attempts for {0}")]
TooManyAttempts(String), TooManyAttempts(String),
#[doc = "unsupported image type"] #[doc = "Unsupported image type"]
#[error("unsupported image type ({0})")] #[error("unsupported image type ({0})")]
UnsupportedImage(String), UnsupportedImage(String),
} }

View file

@ -4,7 +4,7 @@ use identicon_rs::{error::IdenticonError, Identicon};
#[macros::errors] #[macros::errors]
pub enum Error { pub enum Error {
#[doc = "failed to generate identicon"] #[doc = "Failed to generate identicon"]
#[error(transparent)] #[error(transparent)]
Identicon(#[from] IdenticonError), Identicon(#[from] IdenticonError),
#[error("Redis cache operation has failed")] #[error("Redis cache operation has failed")]

View file

@ -6,13 +6,13 @@ use sea_orm::{DbErr, EntityTrait, QuerySelect};
#[macros::errors] #[macros::errors]
pub enum Error { pub enum Error {
#[doc = "database error"] #[doc = "Database error"]
#[error(transparent)] #[error(transparent)]
Db(#[from] DbErr), Db(#[from] DbErr),
#[doc = "cache error"] #[doc = "Cache error"]
#[error(transparent)] #[error(transparent)]
Cache(#[from] cache::redis::Error), Cache(#[from] cache::redis::Error),
#[doc = "user not found"] #[doc = "User not found"]
#[error("user {0} not found")] #[error("user {0} not found")]
NotFound(String), NotFound(String),
} }

View file

@ -5,7 +5,7 @@ use crate::{
#[macros::errors] #[macros::errors]
pub enum Error { pub enum Error {
#[doc = "database error"] #[doc = "Database error"]
#[error(transparent)] #[error(transparent)]
Db(#[from] sea_orm::DbErr), Db(#[from] sea_orm::DbErr),
#[error("failed to acquire an HTTP client")] #[error("failed to acquire an HTTP client")]

View file

@ -10,7 +10,7 @@ use sea_orm::{prelude::*, QuerySelect};
#[macros::errors] #[macros::errors]
pub enum AntennaCheckError { pub enum AntennaCheckError {
#[doc = "database error"] #[doc = "Database error"]
#[error(transparent)] #[error(transparent)]
Db(#[from] DbErr), Db(#[from] DbErr),
#[error("Redis cache operation has failed")] #[error("Redis cache operation has failed")]

View file

@ -16,7 +16,7 @@ use sea_orm::prelude::*;
#[macros::errors] #[macros::errors]
pub enum Error { pub enum Error {
#[doc = "database error"] #[doc = "Database error"]
#[error(transparent)] #[error(transparent)]
Db(#[from] DbErr), Db(#[from] DbErr),
#[error("Redis cache operation has failed")] #[error("Redis cache operation has failed")]
@ -25,7 +25,7 @@ pub enum Error {
Redis(#[from] RedisError), Redis(#[from] RedisError),
#[error("bad Redis connection")] #[error("bad Redis connection")]
RedisConn(#[from] RedisConnError), RedisConn(#[from] RedisConnError),
#[doc = "provided string is not a valid Firefish ID"] #[doc = "Provided string is not a valid Firefish ID"]
#[error(transparent)] #[error(transparent)]
InvalidId(#[from] InvalidIdError), InvalidId(#[from] InvalidIdError),
#[error("Redis stream operation has failed")] #[error("Redis stream operation has failed")]

View file

@ -15,17 +15,17 @@ use web_push::*;
#[macros::errors] #[macros::errors]
pub enum Error { pub enum Error {
#[doc = "database error"] #[doc = "Database error"]
#[error(transparent)] #[error(transparent)]
Db(#[from] DbErr), Db(#[from] DbErr),
#[error("web push has failed")] #[error("web push has failed")]
WebPush(#[from] WebPushError), WebPush(#[from] WebPushError),
#[error("failed to (de)serialize an object")] #[error("failed to (de)serialize an object")]
Serialize(#[from] serde_json::Error), Serialize(#[from] serde_json::Error),
#[doc = "provided content is invalid"] #[doc = "Provided content is invalid"]
#[error("invalid content ({0})")] #[error("invalid content ({0})")]
InvalidContent(String), InvalidContent(String),
#[doc = "found Mastodon subscription is invalid"] #[doc = "Found Mastodon subscription is invalid"]
#[error("invalid subscription ({0})")] #[error("invalid subscription ({0})")]
InvalidSubscription(String), InvalidSubscription(String),
#[error("invalid notification ID")] #[error("invalid notification ID")]

View file

@ -1,75 +0,0 @@
//! Automatically generate doc comments for error variants from the error messages
use proc_macro2::TokenStream;
use quote::quote;
/// Generates doc comments for error enums.
///
/// # Example
/// ```
/// # use macros_impl::error::error_variants as errors;
/// # macros_impl::macro_doctest!({
/// #[macros::errors]
/// pub enum Error {
/// #[error("config file name is not set")]
/// NoConfigFileName,
/// #[error("failed to read the config file")]
/// ReadConfigFile(#[from] io::Error),
/// #[error("invalid file content ({0})")]
/// #[doc = "invalid file content"]
/// InvalidContent(String),
/// #[error(transparent)]
/// #[doc = "database error"]
/// Db(#[from] sea_orm::DbErr)
/// }
///
/// # }, {
/// /******* the code above expands to *******/
///
/// pub enum Error {
/// #[error("config file name is not set")]
/// #[doc = "config file name is not set"]
/// NoConfigFileName,
/// #[error("failed to read the config file")]
/// #[doc = "failed to read the config file"]
/// ReadConfigFile(#[from] io::Error),
/// #[error("invalid file content ({0})")]
/// #[doc = "invalid file content"]
/// InvalidContent(String),
/// #[error(transparent)]
/// #[doc = "database error"]
/// Db(#[from] sea_orm::DbErr)
/// }
/// # });
/// ```
pub fn error_variants(_attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
let mut item: syn::ItemEnum = syn::parse2(item)?;
item.variants = item
.variants
.into_iter()
.map(|mut variant| {
// check if doc attribute is alredy there
if variant.attrs.iter().any(|attr| attr.path().is_ident("doc")) {
return variant;
}
let msg = variant.attrs.iter().find_map(|attr| {
if !attr.path().is_ident("error") {
return None;
}
let lit: syn::LitStr = attr.parse_args().ok()?;
Some(lit.value())
});
// add #[doc] attribute
if let Some(msg) = msg {
variant.attrs.push(syn::parse_quote! { #[doc = #msg] });
}
variant
})
.collect();
Ok(quote! { #item })
}

View file

@ -1,5 +1,4 @@
#![allow(clippy::items_after_test_module)] #![allow(clippy::items_after_test_module)]
pub mod error;
pub mod napi; pub mod napi;
mod util; mod util;

View file

@ -84,11 +84,9 @@ define_wrapper_proc_macro_attributes! {
/// When applied to enums, this macro implements [`std::error::Error`] trait /// When applied to enums, this macro implements [`std::error::Error`] trait
/// and generates a document based on error messages unless there is already a doc comment /// and generates a document based on error messages unless there is already a doc comment
/// ///
/// See [`macros_impl::error::error_variants`] for more details.
///
/// # Example /// # Example
/// ///
/// ``` /// ```ignore
/// # use std::io; /// # use std::io;
/// #[macros::errors] /// #[macros::errors]
/// pub enum Error { /// pub enum Error {
@ -97,13 +95,13 @@ define_wrapper_proc_macro_attributes! {
/// #[error("failed to read the config file")] /// #[error("failed to read the config file")]
/// ReadConfigFile(#[from] io::Error), /// ReadConfigFile(#[from] io::Error),
/// #[error("invalid file content ({0})")] /// #[error("invalid file content ({0})")]
/// #[doc = "invalid file content"] /// #[doc = "Invalid file content"]
/// InvalidContent(String), /// InvalidContent(String),
/// } /// }
/// ``` /// ```
errors(attr, item) { errors(_attr, item) {
#[derive(::thiserror::Error, ::std::fmt::Debug)] #[derive(::thiserror::Error, ::std::fmt::Debug)]
#[macros::error_variants(#attr, #item)] #[error_doc::error_doc]
#item #item
} }
} }
@ -112,7 +110,4 @@ reexport_proc_macro_attributes! {
/// Creates an extra wrapper function for [napi_derive](https://docs.rs/napi-derive/latest/napi_derive/). /// Creates an extra wrapper function for [napi_derive](https://docs.rs/napi-derive/latest/napi_derive/).
/// See [macros_impl::napi::napi] for details. /// See [macros_impl::napi::napi] for details.
macros_impl::napi::napi as napi macros_impl::napi::napi as napi
/// Generates doc comments for error variants from the error messages
macros_impl::error::error_variants as error_variants
} }