mirror of
https://github.com/fluencelabs/marine-rs-sdk
synced 2025-03-14 22:10:49 +00:00
feat!: allow field attibutes (#121)
This commit is contained in:
parent
7479c36413
commit
7a39cd35ad
@ -34,7 +34,7 @@ impl ParseMacroInput for syn::ItemStruct {
|
|||||||
_ => return syn_error!(self.span(), "only named fields are allowed in structs"),
|
_ => return syn_error!(self.span(), "only named fields are allowed in structs"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let fields = fields_into_ast(fields)?;
|
let fields = fields_into_ast(fields, &self.ident)?;
|
||||||
let fields = AstRecordFields::Named(fields);
|
let fields = AstRecordFields::Named(fields);
|
||||||
|
|
||||||
let name = self.ident.to_string();
|
let name = self.ident.to_string();
|
||||||
@ -64,11 +64,13 @@ fn check_record(record: &syn::ItemStruct) -> Result<()> {
|
|||||||
|
|
||||||
fn fields_into_ast(
|
fn fields_into_ast(
|
||||||
fields: &syn::punctuated::Punctuated<syn::Field, syn::Token![,]>,
|
fields: &syn::punctuated::Punctuated<syn::Field, syn::Token![,]>,
|
||||||
|
record_ident: &syn::Ident,
|
||||||
) -> Result<Vec<AstRecordField>> {
|
) -> Result<Vec<AstRecordField>> {
|
||||||
fields
|
fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
check_field(field)?;
|
maybe_warn_about_non_doc_attributes(field, record_ident);
|
||||||
|
|
||||||
let name = field.ident.as_ref().map(|ident| {
|
let name = field.ident.as_ref().map(|ident| {
|
||||||
ident
|
ident
|
||||||
.to_string()
|
.to_string()
|
||||||
@ -85,23 +87,31 @@ fn fields_into_ast(
|
|||||||
.collect::<Result<Vec<_>>>()
|
.collect::<Result<Vec<_>>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that record fields satisfy the following requirements:
|
/// Prints an error if a field has an any attribute except doc.
|
||||||
/// - field must have only doc attributes
|
fn maybe_warn_about_non_doc_attributes(field: &syn::Field, record_ident: &syn::Ident) {
|
||||||
fn check_field(field: &syn::Field) -> Result<()> {
|
for attr in field.attrs.iter() {
|
||||||
|
match attr.parse_meta() {
|
||||||
|
Ok(meta) if is_doc_attribute(&meta) => continue,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: print message with a span when diagnostic API stabilized
|
||||||
|
// https://github.com/rust-lang/rust/issues/54140
|
||||||
|
match &field.ident {
|
||||||
|
Some(ident) => eprintln!(
|
||||||
|
r#"warning: field "{}" of struct "{}" has an attribute which could cause compatibility issues"#,
|
||||||
|
ident, record_ident
|
||||||
|
),
|
||||||
|
None => eprintln!(
|
||||||
|
r#"warning: field of struct "{}" has an attribute which could cause compatibility issues"#,
|
||||||
|
record_ident
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_doc_attribute(meta: &syn::Meta) -> bool {
|
||||||
const DOC_ATTR_NAME: &str = "doc";
|
const DOC_ATTR_NAME: &str = "doc";
|
||||||
|
|
||||||
// Check that all attributes are doc attributes
|
meta.path().is_ident(DOC_ATTR_NAME)
|
||||||
let are_all_attrs_doc = field.attrs.iter().all(|attr| {
|
|
||||||
let meta = match attr.parse_meta() {
|
|
||||||
Ok(meta) => meta,
|
|
||||||
Err(_) => return false,
|
|
||||||
};
|
|
||||||
meta.path().is_ident(DOC_ATTR_NAME)
|
|
||||||
});
|
|
||||||
|
|
||||||
if !are_all_attrs_doc {
|
|
||||||
return syn_error!(field.span(), "field attributes isn't allowed");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
9
tests/compilation_tests/records/struct_with_attribute.rs
Normal file
9
tests/compilation_tests/records/struct_with_attribute.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use marine_rs_sdk::marine;
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
#[marine]
|
||||||
|
struct A {
|
||||||
|
#[cfg(target_os = "wasm")]
|
||||||
|
pub field: i64,
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
warning: field "field" of struct "A" has an attribute which could cause compatibility issues
|
@ -0,0 +1,9 @@
|
|||||||
|
use marine_rs_sdk::marine;
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
#[marine]
|
||||||
|
struct A {
|
||||||
|
#[doc = "This is a doc attribute"]
|
||||||
|
pub field: i64,
|
||||||
|
}
|
@ -19,6 +19,8 @@ fn marine_compilation_tests() {
|
|||||||
|
|
||||||
tests.pass("tests/compilation_tests/records/basic_structs.rs");
|
tests.pass("tests/compilation_tests/records/basic_structs.rs");
|
||||||
tests.pass("tests/compilation_tests/records/empty_struct.rs");
|
tests.pass("tests/compilation_tests/records/empty_struct.rs");
|
||||||
|
tests.pass("tests/compilation_tests/records/struct_with_attribute.rs");
|
||||||
|
tests.pass("tests/compilation_tests/records/struct_with_doc_attribute.rs");
|
||||||
tests.pass("tests/compilation_tests/records/struct_with_private_fields.rs");
|
tests.pass("tests/compilation_tests/records/struct_with_private_fields.rs");
|
||||||
tests.compile_fail("tests/compilation_tests/records/struct_with_improper_types.rs");
|
tests.compile_fail("tests/compilation_tests/records/struct_with_improper_types.rs");
|
||||||
tests.compile_fail("tests/compilation_tests/records/unnamed_structs.rs");
|
tests.compile_fail("tests/compilation_tests/records/unnamed_structs.rs");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user