-
-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
531: refactor the `macros` crate r=japaric a=japaric ~~NOT READY FOR REVIEW. I just wanted to signal that I'm working on this~~ 534: defmt-test: attribute test progress message to the test in question r=japaric a=jonas-schievink Sets the span of the tokens making up the `defmt::info!` call to the test function's identifier. Fixes #425 ``` INFO (1/11) running `split_filters`... └─ integration::tests::__defmt_test_entry @ tests/integration.rs:18 INFO (2/11) running `basic_roundtrip`... └─ integration::tests::__defmt_test_entry @ tests/integration.rs:43 INFO (3/11) running `no_filters_no_frames`... └─ integration::tests::__defmt_test_entry @ tests/integration.rs:58 INFO (4/11) running `filter_mask32_std`... └─ integration::tests::__defmt_test_entry @ tests/integration.rs:68 INFO (5/11) running `filter_mask32_ext`... └─ integration::tests::__defmt_test_entry @ tests/integration.rs:112 INFO (6/11) running `filter_mask16`... └─ integration::tests::__defmt_test_entry @ tests/integration.rs:153 INFO (7/11) running `filter_list32_std`... └─ integration::tests::__defmt_test_entry @ tests/integration.rs:193 INFO (8/11) running `filter_list32_ext`... └─ integration::tests::__defmt_test_entry @ tests/integration.rs:226 INFO (9/11) running `dequeue_lower_priority_frame`... └─ integration::tests::__defmt_test_entry @ tests/integration.rs:264 INFO (10/11) running `enable_non_blocking`... └─ integration::tests::__defmt_test_entry @ tests/integration.rs:317 INFO (11/11) running `ext_roundtrip`... └─ integration::tests::__defmt_test_entry @ tests/integration.rs:330 ``` (this was pretty painful to test, since qemu-run does not print location information, and probe-run doesn't use git defmt out of the box, so I had to edit its Cargo.toml, and then make bxcan use git defmt) Co-authored-by: Jorge Aparicio <jorge.aparicio@ferrous-systems.com> Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
- Loading branch information
Showing
38 changed files
with
1,703 additions
and
1,382 deletions.
There are no files selected for viewing
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,4 @@ | ||
//! Procedural macros that are attributes | ||
pub(crate) mod global_logger; | ||
pub(crate) mod panic_handler; |
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,57 @@ | ||
use proc_macro::TokenStream; | ||
use proc_macro_error::{abort, abort_call_site}; | ||
use quote::quote; | ||
use syn::{parse_macro_input, Fields, ItemStruct}; | ||
|
||
pub(crate) fn expand(args: TokenStream, item: TokenStream) -> TokenStream { | ||
if !args.is_empty() { | ||
abort_call_site!("`#[global_logger]` attribute takes no arguments") | ||
} | ||
|
||
let strukt = parse_macro_input!(item as ItemStruct); | ||
|
||
validate(&strukt); | ||
|
||
codegen(&strukt) | ||
} | ||
|
||
fn validate(strukt: &ItemStruct) { | ||
let is_unit_struct = matches!(strukt.fields, Fields::Unit); | ||
|
||
if !strukt.generics.params.is_empty() | ||
|| strukt.generics.where_clause.is_some() | ||
|| !is_unit_struct | ||
{ | ||
abort!( | ||
strukt, | ||
"struct must be a non-generic unit struct (e.g. `struct S;`)" | ||
); | ||
} | ||
} | ||
|
||
fn codegen(strukt: &ItemStruct) -> TokenStream { | ||
let attrs = &strukt.attrs; | ||
let ident = &strukt.ident; | ||
let vis = &strukt.vis; | ||
|
||
quote!( | ||
#(#attrs)* | ||
#vis struct #ident; | ||
|
||
#[no_mangle] | ||
unsafe fn _defmt_acquire() { | ||
<#ident as defmt::Logger>::acquire() | ||
} | ||
|
||
#[no_mangle] | ||
unsafe fn _defmt_release() { | ||
<#ident as defmt::Logger>::release() | ||
} | ||
|
||
#[no_mangle] | ||
unsafe fn _defmt_write(bytes: &[u8]) { | ||
<#ident as defmt::Logger>::write(bytes) | ||
} | ||
) | ||
.into() | ||
} |
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,77 @@ | ||
use proc_macro::TokenStream; | ||
use proc_macro_error::{abort, abort_call_site}; | ||
use quote::quote; | ||
use syn::{parse_macro_input, Attribute, ItemFn, ReturnType, Type}; | ||
|
||
pub(crate) fn expand(args: TokenStream, item: TokenStream) -> TokenStream { | ||
if !args.is_empty() { | ||
abort_call_site!("`#[defmt::panic_handler]` attribute takes no arguments"); | ||
} | ||
|
||
let fun = parse_macro_input!(item as ItemFn); | ||
|
||
validate(&fun); | ||
|
||
codegen(&fun) | ||
} | ||
|
||
fn validate(fun: &ItemFn) { | ||
let is_divergent = match &fun.sig.output { | ||
ReturnType::Default => false, | ||
ReturnType::Type(_, ty) => matches!(&**ty, Type::Never(_)), | ||
}; | ||
|
||
if fun.sig.constness.is_some() | ||
|| fun.sig.asyncness.is_some() | ||
|| fun.sig.unsafety.is_some() | ||
|| fun.sig.abi.is_some() | ||
|| !fun.sig.generics.params.is_empty() | ||
|| fun.sig.generics.where_clause.is_some() | ||
|| fun.sig.variadic.is_some() | ||
|| !fun.sig.inputs.is_empty() | ||
|| !is_divergent | ||
{ | ||
abort!(fun.sig.ident, "function must have signature `fn() -> !`"); | ||
} | ||
|
||
check_for_attribute_conflicts("panic_handler", &fun.attrs, &["export_name", "no_mangle"]); | ||
} | ||
|
||
/// Checks if any attribute in `attrs_to_check` is in `reject_list` and returns a compiler error if there's a match | ||
/// | ||
/// The compiler error will indicate that the attribute conflicts with `attr_name` | ||
fn check_for_attribute_conflicts( | ||
attr_name: &str, | ||
attrs_to_check: &[Attribute], | ||
reject_list: &[&str], | ||
) { | ||
for attr in attrs_to_check { | ||
if let Some(ident) = attr.path.get_ident() { | ||
let ident = ident.to_string(); | ||
|
||
if reject_list.contains(&ident.as_str()) { | ||
abort!( | ||
attr, | ||
"`#[{}]` attribute cannot be used together with `#[{}]`", | ||
attr_name, | ||
ident | ||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
fn codegen(fun: &ItemFn) -> TokenStream { | ||
let attrs = &fun.attrs; | ||
let block = &fun.block; | ||
let ident = &fun.sig.ident; | ||
|
||
quote!( | ||
#(#attrs)* | ||
#[export_name = "_defmt_panic"] | ||
fn #ident() -> ! { | ||
#block | ||
} | ||
) | ||
.into() | ||
} |
This file was deleted.
Oops, something went wrong.
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,5 @@ | ||
use std::env; | ||
|
||
pub(crate) fn package_name() -> String { | ||
env::var("CARGO_PKG_NAME").unwrap_or_else(|_| "<unknown>".to_string()) | ||
} |
Oops, something went wrong.