mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 20:33:54 -06:00
rust: qemu-api-macros: extend error reporting facility to parse errors
Generalize the CompileError tuple to an enum, that can be either an error message or a parse error from syn. Reviewed-by: Zhao Liu <zhao1.liu@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
22a18f0a98
commit
a3b620fff7
2 changed files with 36 additions and 17 deletions
|
@ -3,57 +3,50 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::Span;
|
||||
use quote::{quote, quote_spanned};
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
parse_macro_input, parse_quote, punctuated::Punctuated, token::Comma, Data, DeriveInput, Field,
|
||||
Fields, Ident, Type, Visibility,
|
||||
};
|
||||
|
||||
struct CompileError(String, Span);
|
||||
|
||||
impl From<CompileError> for proc_macro2::TokenStream {
|
||||
fn from(err: CompileError) -> Self {
|
||||
let CompileError(msg, span) = err;
|
||||
quote_spanned! { span => compile_error!(#msg); }
|
||||
}
|
||||
}
|
||||
mod utils;
|
||||
use utils::MacroError;
|
||||
|
||||
fn get_fields<'a>(
|
||||
input: &'a DeriveInput,
|
||||
msg: &str,
|
||||
) -> Result<&'a Punctuated<Field, Comma>, CompileError> {
|
||||
) -> Result<&'a Punctuated<Field, Comma>, MacroError> {
|
||||
if let Data::Struct(s) = &input.data {
|
||||
if let Fields::Named(fs) = &s.fields {
|
||||
Ok(&fs.named)
|
||||
} else {
|
||||
Err(CompileError(
|
||||
Err(MacroError::Message(
|
||||
format!("Named fields required for {}", msg),
|
||||
input.ident.span(),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
Err(CompileError(
|
||||
Err(MacroError::Message(
|
||||
format!("Struct required for {}", msg),
|
||||
input.ident.span(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn is_c_repr(input: &DeriveInput, msg: &str) -> Result<(), CompileError> {
|
||||
fn is_c_repr(input: &DeriveInput, msg: &str) -> Result<(), MacroError> {
|
||||
let expected = parse_quote! { #[repr(C)] };
|
||||
|
||||
if input.attrs.iter().any(|attr| attr == &expected) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(CompileError(
|
||||
Err(MacroError::Message(
|
||||
format!("#[repr(C)] required for {}", msg),
|
||||
input.ident.span(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn derive_object_or_error(input: DeriveInput) -> Result<proc_macro2::TokenStream, CompileError> {
|
||||
fn derive_object_or_error(input: DeriveInput) -> Result<proc_macro2::TokenStream, MacroError> {
|
||||
is_c_repr(&input, "#[derive(Object)]")?;
|
||||
|
||||
let name = &input.ident;
|
||||
|
@ -80,7 +73,7 @@ pub fn derive_object(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
|
||||
#[rustfmt::skip::macros(quote)]
|
||||
fn derive_offsets_or_error(input: DeriveInput) -> Result<proc_macro2::TokenStream, CompileError> {
|
||||
fn derive_offsets_or_error(input: DeriveInput) -> Result<proc_macro2::TokenStream, MacroError> {
|
||||
is_c_repr(&input, "#[derive(offsets)]")?;
|
||||
|
||||
let name = &input.ident;
|
||||
|
|
26
rust/qemu-api-macros/src/utils.rs
Normal file
26
rust/qemu-api-macros/src/utils.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Procedural macro utilities.
|
||||
// Author(s): Paolo Bonzini <pbonzini@redhat.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
use proc_macro2::Span;
|
||||
use quote::quote_spanned;
|
||||
|
||||
pub enum MacroError {
|
||||
Message(String, Span),
|
||||
ParseError(syn::Error),
|
||||
}
|
||||
|
||||
impl From<syn::Error> for MacroError {
|
||||
fn from(err: syn::Error) -> Self {
|
||||
MacroError::ParseError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MacroError> for proc_macro2::TokenStream {
|
||||
fn from(err: MacroError) -> Self {
|
||||
match err {
|
||||
MacroError::Message(msg, span) => quote_spanned! { span => compile_error!(#msg); },
|
||||
MacroError::ParseError(err) => err.into_compile_error(),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue