forked from mozilla/uniffi-rs
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is prep work for implementing the system for remote / custom / external types as described in mozilla#2087. The generated code should stay exactly the same, this just refactors how it's generated. Consolidated the `derive_*_for_udl` macros into a single `udl_derive` macro and added the `DeriveOptions` struct. My plan is to re-use this pattern remote types (with `generate_metadata: true, local_tag: true`). This also simplifies the task of switching UDL to generate blanket FFI trait impls. Changed the specific derive code to use `DeriveOptions` plus an item struct. For example RecordItem, which represents the parsed DeriveInput for the record. This will make future changes easier since we only need to modify one of these structs, not update all the function signatures. Changed the UDL derives to parse attributes exactly like regular derives. For example, we now wrap enums with `#[uniffi(flat_error)]` rather than putting `flat_error` in the `derive_error_for_udl` attribute macro. This is prep work for remote types -- in that case I think we should tell the user to define the item exactly like it was a regular derive and not special case the attributes. Removed the `#[uniffi(non_exhaustive)]` attribute and parse the real `#[non_exhaustive]` attribute instead. This is easy to do now with the new system and also will be good for remote types. Made EnumItem also parse error attributes. I think this is simpler than creating a separate EnumItem vs ErrorItem, at least for now.
- Loading branch information
Showing
14 changed files
with
479 additions
and
391 deletions.
There are no files selected for viewing
9 changes: 3 additions & 6 deletions
9
fixtures/uitests/tests/ui/fieldless_errors_used_in_callbacks_cant_have_fields.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,7 @@ | ||
error[E0533]: expected value, found struct variant `Self::DivisionByZero` | ||
--> $OUT_DIR[uniffi_uitests]/errors.uniffi.rs | ||
| | ||
| / #[::uniffi::derive_error_for_udl( | ||
| | flat_error, | ||
| | with_try_read, | ||
| | )] | ||
| |__^ not a value | ||
| #[::uniffi::udl_derive(Error)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a value | ||
| | ||
= note: this error originates in the attribute macro `::uniffi::derive_error_for_udl` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
= note: this error originates in the attribute macro `::uniffi::udl_derive` (in Nightly builds, run with -Z macro-backtrace for more info) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
//! General handling for the derive and udl_derive macros | ||
use crate::util::kw; | ||
use proc_macro2::{Ident, Span, TokenStream}; | ||
use quote::{quote, ToTokens}; | ||
use syn::{ | ||
parse::{Parse, ParseStream}, | ||
DeriveInput, | ||
}; | ||
|
||
pub fn expand_derive( | ||
kind: DeriveKind, | ||
input: DeriveInput, | ||
options: DeriveOptions, | ||
) -> syn::Result<TokenStream> { | ||
match kind { | ||
DeriveKind::Record(_) => crate::record::expand_record(input, options), | ||
DeriveKind::Object(_) => crate::object::expand_object(input, options), | ||
DeriveKind::Enum(_) => crate::enum_::expand_enum(input, options), | ||
DeriveKind::Error(_) => crate::error::expand_error(input, options), | ||
} | ||
} | ||
|
||
pub enum DeriveKind { | ||
Record(kw::Record), | ||
Enum(kw::Enum), | ||
Error(kw::Error), | ||
Object(kw::Object), | ||
} | ||
|
||
impl Parse for DeriveKind { | ||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> { | ||
let lookahead = input.lookahead1(); | ||
if lookahead.peek(kw::Record) { | ||
Ok(Self::Record(input.parse()?)) | ||
} else if lookahead.peek(kw::Enum) { | ||
Ok(Self::Enum(input.parse()?)) | ||
} else if lookahead.peek(kw::Error) { | ||
Ok(Self::Error(input.parse()?)) | ||
} else if lookahead.peek(kw::Object) { | ||
Ok(Self::Object(input.parse()?)) | ||
} else { | ||
Err(lookahead.error()) | ||
} | ||
} | ||
} | ||
|
||
pub struct DeriveOptions { | ||
/// Should we implement FFI traits for the local UniFfiTag only? | ||
pub local_tag: bool, | ||
/// Should we generate metadata symbols? | ||
pub generate_metadata: bool, | ||
} | ||
|
||
/// default() is used to construct a DeriveOptions for a regular `derive` invocation | ||
impl Default for DeriveOptions { | ||
fn default() -> Self { | ||
Self { | ||
local_tag: false, | ||
generate_metadata: true, | ||
} | ||
} | ||
} | ||
|
||
impl DeriveOptions { | ||
/// Construct DeriveOptions for `udl_derive` | ||
pub fn udl_derive() -> Self { | ||
Self { | ||
local_tag: true, | ||
generate_metadata: false, | ||
} | ||
} | ||
|
||
/// Generate the impl header for a FFI trait | ||
/// | ||
/// This will output something like `impl<UT> FfiConverter<UT> for #type`. The caller is | ||
/// responsible for providing the body if the impl block. | ||
pub fn ffi_impl_header(&self, trait_name: &str, ident: &impl ToTokens) -> TokenStream { | ||
let trait_name = Ident::new(trait_name, Span::call_site()); | ||
if self.local_tag { | ||
quote! { impl ::uniffi::#trait_name<crate::UniFfiTag> for #ident } | ||
} else { | ||
quote! { impl<UT> ::uniffi::#trait_name<UT> for #ident } | ||
} | ||
} | ||
|
||
/// Generate a call to `derive_ffi_traits!` that will derive all the FFI traits | ||
pub fn derive_all_ffi_traits(&self, ty: &Ident) -> TokenStream { | ||
if self.local_tag { | ||
quote! { ::uniffi::derive_ffi_traits!(local #ty); } | ||
} else { | ||
quote! { ::uniffi::derive_ffi_traits!(blanket #ty); } | ||
} | ||
} | ||
|
||
/// Generate a call to `derive_ffi_traits!` that will derive some of the FFI traits | ||
pub fn derive_ffi_traits(&self, ty: impl ToTokens, trait_names: &[&str]) -> TokenStream { | ||
let trait_idents = trait_names | ||
.iter() | ||
.map(|name| Ident::new(name, Span::call_site())); | ||
if self.local_tag { | ||
quote! { | ||
#( | ||
::uniffi::derive_ffi_traits!(impl #trait_idents<crate::UniFfiTag> for #ty); | ||
)* | ||
} | ||
} else { | ||
quote! { | ||
#( | ||
::uniffi::derive_ffi_traits!(impl<UT> #trait_idents<UT> for #ty); | ||
)* | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.