Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ pub(crate) struct Field {

impl Field {
pub(crate) fn build(field: &SynField, index: usize) -> syn::Result<Field> {
let span = field.span();
let member = match field.ident.clone() {
Some(ident) => Member::Named(ident),
None => Member::Unnamed(Index {
Expand All @@ -27,6 +26,8 @@ impl Field {

let ty = field.ty.clone();

let span = member.span().join(ty.span()).unwrap_or(ty.span());

let doc = field
.attrs
.iter()
Expand Down
10 changes: 5 additions & 5 deletions src/field_attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) struct FieldAttributes {
pub(crate) decorated: bool,
pub(crate) fn_ident: Option<Ident>,
pub(crate) argument_ident: Option<Ident>,
pub(crate) method_attributes: MethodSettings<FieldMethodAttributes>,
pub(crate) method_attributes: MethodSettings<(Span, FieldMethodAttributes)>,
pub(crate) deref: Option<Type>,

pub(crate) common_settings: CommonSettings,
Expand Down Expand Up @@ -96,7 +96,7 @@ impl FieldAttributes {
)
})?;
self.method_attributes
.insert(method, FieldMethodAttributes::build(args)?);
.insert(method, (expr.span(), FieldMethodAttributes::build(args)?));
}

func => {
Expand Down Expand Up @@ -152,7 +152,7 @@ impl FieldAttributes {
..FieldMethodAttributes::default()
};

self.method_attributes.insert(method, fma);
self.method_attributes.insert(method, (span, fma));
}
}
}
Expand All @@ -178,7 +178,7 @@ impl FieldAttributes {
..FieldMethodAttributes::default()
};

self.method_attributes.insert(method, fma);
self.method_attributes.insert(method, (span, fma));
}
}
Ok(())
Expand All @@ -198,7 +198,7 @@ impl FieldAttributes {
..FieldMethodAttributes::default()
};

self.method_attributes.insert(method, fma);
self.method_attributes.insert(method, (span, fma));
Ok(())
}
}
Expand Down
36 changes: 23 additions & 13 deletions src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ use crate::{
option_handling::{extract_option_type, strip_ref},
};
use Method::{Get, GetMut, Set, With, Without};
use proc_macro2::Span;
use syn::{Expr, Ident, Member, Type, Visibility, parse_quote};

#[cfg_attr(feature = "debug", derive(Debug))]
pub(crate) struct Query<'a> {
method: &'a Method,
field: &'a Field,
struct_attributes: &'a StructAttributes,
field_method_attributes: Option<&'a FieldMethodAttributes>,
method: &'a Method,
span: &'a Span,
struct_attributes: &'a StructAttributes,
struct_method_attributes: Option<&'a StructMethodAttributes>,
}

Expand All @@ -25,14 +27,20 @@ impl<'a> Query<'a> {
field: &'a Field,
struct_attributes: &'a StructAttributes,
) -> Self {
let field_method_attributes = field.attributes.method_attributes.retrieve(*method);
let (span, field_method_attributes) = field
.attributes
.method_attributes
.retrieve(*method)
.map_or((None, None), |(s, fma)| (Some(s), Some(fma)));
let struct_method_attributes = struct_attributes.methods.retrieve(*method);
let span = span.unwrap_or(&field.span);

Self {
method,
field,
struct_attributes,
field_method_attributes,
method,
span,
struct_attributes,
struct_method_attributes,
}
}
Expand All @@ -41,6 +49,7 @@ impl<'a> Query<'a> {
if !self.enabled() {
return None;
}
let span = *self.span;
let method = *self.method;
let vis = self.vis();
let fn_ident = self.fn_ident()?;
Expand All @@ -58,18 +67,19 @@ impl<'a> Query<'a> {
let argument_ident_and_ty = argument_ty.map(|ty| (argument_ident, ty));

Some(Resolved {
method,
vis,
fn_ident,
variable_ident,
argument_ident_and_ty,
ty,
doc,
get_copy,
assigned_value,
chainable_set,
deref_type,
doc,
fn_ident,
get_copy,
method,
option_borrow_inner,
assigned_value,
span,
ty,
variable_ident,
vis,
})
}

Expand Down
54 changes: 30 additions & 24 deletions src/resolved.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
use crate::{Method, query::OptionHandling};
use Method::{Get, GetMut, Set, With, Without};
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{quote, quote_spanned};
use std::borrow::Cow;
use syn::{Expr, Ident, Member, Type, Visibility};

#[cfg_attr(feature = "debug", derive(Debug))]
pub(crate) struct Resolved<'a> {
pub(crate) method: Method,
pub(crate) vis: Cow<'a, Visibility>,
pub(crate) fn_ident: Cow<'a, Ident>,
pub(crate) variable_ident: &'a Member,
pub(crate) argument_ident_and_ty: Option<(Cow<'a, Ident>, Cow<'a, Type>)>,
pub(crate) ty: &'a Type,
pub(crate) doc: Option<Cow<'a, str>>,
pub(crate) get_copy: bool,
pub(crate) assigned_value: Expr,
pub(crate) chainable_set: bool,
pub(crate) deref_type: Option<Cow<'a, Type>>,
pub(crate) doc: Option<Cow<'a, str>>,
pub(crate) fn_ident: Cow<'a, Ident>,
pub(crate) get_copy: bool,
pub(crate) method: Method,
pub(crate) option_borrow_inner: Option<OptionHandling<'a>>,
pub(crate) assigned_value: Expr,
pub(crate) span: Span,
pub(crate) ty: &'a Type,
pub(crate) variable_ident: &'a Member,
pub(crate) vis: Cow<'a, Visibility>,
}

impl Resolved<'_> {
Expand All @@ -32,41 +33,42 @@ impl Resolved<'_> {
get_copy,
deref_type,
option_borrow_inner,
span,
..
} = self;
let doc = doc.as_deref().map(|d| quote!(#[doc = #d]));

if *get_copy {
quote! {
quote_spanned! {*span=>
#doc
#vis fn #fn_ident(&self) -> #ty {
self.#variable_ident
}
}
} else if let Some(oh) = option_borrow_inner {
match oh {
OptionHandling::Deref(ty) => quote! {
OptionHandling::Deref(ty) => quote_spanned! {*span=>
#doc
#vis fn #fn_ident(&self) -> Option<&#ty> {
self.#variable_ident.as_deref()
}
},
OptionHandling::Ref(ty) => quote! {
OptionHandling::Ref(ty) => quote_spanned! {*span=>
#doc
#vis fn #fn_ident(&self) -> Option<&#ty> {
self.#variable_ident.as_ref()
}
},
}
} else if let Some(deref) = deref_type {
quote! {
quote_spanned! {*span=>
#doc
#vis fn #fn_ident(&self) -> &#deref {
&*self.#variable_ident
}
}
} else {
quote! {
quote_spanned! {*span=>
#doc
#vis fn #fn_ident(&self) -> &#ty {
&self.#variable_ident
Expand All @@ -84,6 +86,7 @@ impl Resolved<'_> {
chainable_set,
assigned_value,
argument_ident_and_ty,
span,
..
} = self;

Expand All @@ -94,15 +97,15 @@ impl Resolved<'_> {
let doc = doc.as_deref().map(|d| quote!(#[doc = #d]));

if *chainable_set {
quote! {
quote_spanned! {*span=>
#doc
#vis fn #fn_ident(&mut self, #argument_ident: #argument_ty) -> &mut Self {
self.#variable_ident = #assigned_value;
self
}
}
} else {
quote! {
quote_spanned! {*span=>
#doc
#vis fn #fn_ident(&mut self, #argument_ident: #argument_ty) {
self.#variable_ident = #assigned_value;
Expand All @@ -120,34 +123,35 @@ impl Resolved<'_> {
doc,
deref_type,
option_borrow_inner,
span,
..
} = self;
let doc = doc.as_deref().map(|d| quote!(#[doc = #d]));

if let Some(oh) = option_borrow_inner {
match oh {
OptionHandling::Deref(ty) => quote! {
OptionHandling::Deref(ty) => quote_spanned! {*span=>
#doc
#vis fn #fn_ident(&mut self) -> Option<&mut #ty> {
self.#variable_ident.as_deref_mut()
}
},
OptionHandling::Ref(ty) => quote! {
OptionHandling::Ref(ty) => quote_spanned! {*span=>
#doc
#vis fn #fn_ident(&mut self) -> Option<&mut #ty> {
self.#variable_ident.as_mut()
}
},
}
} else if let Some(deref) = deref_type {
quote! {
quote_spanned! {*span=>
#doc
#vis fn #fn_ident(&mut self) -> &mut #deref {
&mut *self.#variable_ident
}
}
} else {
quote! {
quote_spanned! {*span=>
#doc
#vis fn #fn_ident(&mut self) -> &mut #ty {
&mut self.#variable_ident
Expand All @@ -164,11 +168,12 @@ impl Resolved<'_> {
argument_ident_and_ty,
doc,
assigned_value,
span,
..
} = self;
let doc = doc.as_deref().map(|d| quote!(#[doc = #d]));
if let Some((argument_ident, argument_ty)) = argument_ident_and_ty {
quote! {
quote_spanned! {*span=>
#doc
#[must_use]
#vis fn #fn_ident(mut self, #argument_ident: #argument_ty) -> Self {
Expand All @@ -177,7 +182,7 @@ impl Resolved<'_> {
}
}
} else {
quote! {
quote_spanned! {*span=>
#doc
#[must_use]
#vis fn #fn_ident(mut self) -> Self {
Expand Down Expand Up @@ -205,11 +210,12 @@ impl Resolved<'_> {
variable_ident,
doc,
assigned_value,
span,
..
} = self;
let doc = doc.as_deref().map(|d| quote!(#[doc = #d]));

quote! {
quote_spanned! {*span=>
#doc
#[must_use]
#vis fn #fn_ident(mut self) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn ui_tests() {

#[rustversion::not(stable)]
#[test]
#[ignore]
#[ignore = "to run ui tests, use the stable toolchain"]
fn ui_tests() {
ui_tests_impl()
}
Expand Down
14 changes: 14 additions & 0 deletions tests/ui/compile_error_in_generated_content.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[derive(fieldwork::Fieldwork)]
struct Something {
#[fieldwork(get, deref = "()")]
string: String,
}

#[derive(fieldwork::Fieldwork)]
#[fieldwork(get)]
struct SomethingElse {
#[fieldwork(deref = "()")]
string: String,
}

fn main() {}
27 changes: 27 additions & 0 deletions tests/ui/compile_error_in_generated_content.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
error[E0308]: mismatched types
--> tests/ui/compile_error_in_generated_content.rs:3:17
|
3 | #[fieldwork(get, deref = "()")]
| ^----------------
| |
| _________________expected `&()` because of return type
| |
4 | | string: String,
| |__________^ expected `&()`, found `&str`
|
= note: expected reference `&()`
found reference `&str`

error[E0308]: mismatched types
--> tests/ui/compile_error_in_generated_content.rs:11:5
|
10 | #[fieldwork(deref = "()")]
| _________________________-
11 | | string: String,
| | ^^^^^^^^^^^^^-
| |_____|____________|
| | expected `&()` because of return type
| expected `&()`, found `&str`
|
= note: expected reference `&()`
found reference `&str`
Loading